ec618db3f854b6aa934b90030e76837ad5810647
[samba.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2004.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_send;
32 extern int max_recv;
33 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
431         return ret;
432 }
433
434 /****************************************************************************
435  Pull a string and check the path - provide for error return.
436 ****************************************************************************/
437
438 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
439 {
440         pstring tmppath;
441         char *tmppath_ptr = tmppath;
442         size_t ret;
443 #ifdef DEVELOPER
444         SMB_ASSERT(dest_len == sizeof(pstring));
445 #endif
446
447         if (src_len == 0) {
448                 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
449         } else {
450                 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
451         }
452         if (lp_posix_pathnames()) {
453                 *err = check_path_syntax_posix(dest, tmppath);
454         } else {
455                 *err = check_path_syntax(dest, tmppath);
456         }
457
458         return ret;
459 }
460
461 /****************************************************************************
462  Reply to a special message.
463 ****************************************************************************/
464
465 int reply_special(char *inbuf,char *outbuf)
466 {
467         int outsize = 4;
468         int msg_type = CVAL(inbuf,0);
469         int msg_flags = CVAL(inbuf,1);
470         fstring name1,name2;
471         char name_type = 0;
472         
473         static BOOL already_got_session = False;
474
475         *name1 = *name2 = 0;
476         
477         memset(outbuf,'\0',smb_size);
478
479         smb_setlen(outbuf,0);
480         
481         switch (msg_type) {
482         case 0x81: /* session request */
483                 
484                 if (already_got_session) {
485                         exit_server("multiple session request not permitted");
486                 }
487                 
488                 SCVAL(outbuf,0,0x82);
489                 SCVAL(outbuf,3,0);
490                 if (name_len(inbuf+4) > 50 || 
491                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
492                         DEBUG(0,("Invalid name length in session request\n"));
493                         return(0);
494                 }
495                 name_extract(inbuf,4,name1);
496                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
497                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
498                          name1,name2));      
499
500                 set_local_machine_name(name1, True);
501                 set_remote_machine_name(name2, True);
502
503                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
504                          get_local_machine_name(), get_remote_machine_name(),
505                          name_type));
506
507                 if (name_type == 'R') {
508                         /* We are being asked for a pathworks session --- 
509                            no thanks! */
510                         SCVAL(outbuf, 0,0x83);
511                         break;
512                 }
513
514                 /* only add the client's machine name to the list
515                    of possibly valid usernames if we are operating
516                    in share mode security */
517                 if (lp_security() == SEC_SHARE) {
518                         add_session_user(get_remote_machine_name());
519                 }
520
521                 reload_services(True);
522                 reopen_logs();
523
524                 already_got_session = True;
525                 break;
526                 
527         case 0x89: /* session keepalive request 
528                       (some old clients produce this?) */
529                 SCVAL(outbuf,0,SMBkeepalive);
530                 SCVAL(outbuf,3,0);
531                 break;
532                 
533         case 0x82: /* positive session response */
534         case 0x83: /* negative session response */
535         case 0x84: /* retarget session response */
536                 DEBUG(0,("Unexpected session response\n"));
537                 break;
538                 
539         case SMBkeepalive: /* session keepalive */
540         default:
541                 return(0);
542         }
543         
544         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
545                     msg_type, msg_flags));
546         
547         return(outsize);
548 }
549
550 /****************************************************************************
551  Reply to a tcon.
552  conn POINTER CAN BE NULL HERE !
553 ****************************************************************************/
554
555 int reply_tcon(connection_struct *conn,
556                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
557 {
558         const char *service;
559         pstring service_buf;
560         pstring password;
561         pstring dev;
562         int outsize = 0;
563         uint16 vuid = SVAL(inbuf,smb_uid);
564         int pwlen=0;
565         NTSTATUS nt_status;
566         char *p;
567         DATA_BLOB password_blob;
568         
569         START_PROFILE(SMBtcon);
570
571         *service_buf = *password = *dev = 0;
572
573         p = smb_buf(inbuf)+1;
574         p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
575         pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
576         p += pwlen;
577         p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
578
579         p = strrchr_m(service_buf,'\\');
580         if (p) {
581                 service = p+1;
582         } else {
583                 service = service_buf;
584         }
585
586         password_blob = data_blob(password, pwlen+1);
587
588         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
589
590         data_blob_clear_free(&password_blob);
591   
592         if (!conn) {
593                 END_PROFILE(SMBtcon);
594                 return ERROR_NT(nt_status);
595         }
596   
597         outsize = set_message(outbuf,2,0,True);
598         SSVAL(outbuf,smb_vwv0,max_recv);
599         SSVAL(outbuf,smb_vwv1,conn->cnum);
600         SSVAL(outbuf,smb_tid,conn->cnum);
601   
602         DEBUG(3,("tcon service=%s cnum=%d\n", 
603                  service, conn->cnum));
604   
605         END_PROFILE(SMBtcon);
606         return(outsize);
607 }
608
609 /****************************************************************************
610  Reply to a tcon and X.
611  conn POINTER CAN BE NULL HERE !
612 ****************************************************************************/
613
614 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
615 {
616         fstring service;
617         DATA_BLOB password;
618
619         /* what the cleint thinks the device is */
620         fstring client_devicetype;
621         /* what the server tells the client the share represents */
622         const char *server_devicetype;
623         NTSTATUS nt_status;
624         uint16 vuid = SVAL(inbuf,smb_uid);
625         int passlen = SVAL(inbuf,smb_vwv3);
626         pstring path;
627         char *p, *q;
628         
629         START_PROFILE(SMBtconX);        
630
631         *service = *client_devicetype = 0;
632
633         /* we might have to close an old one */
634         if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
635                 close_cnum(conn,vuid);
636         }
637
638         if (passlen > MAX_PASS_LEN) {
639                 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
640         }
641  
642         if (global_encrypted_passwords_negotiated) {
643                 password = data_blob(smb_buf(inbuf),passlen);
644         } else {
645                 password = data_blob(smb_buf(inbuf),passlen+1);
646                 /* Ensure correct termination */
647                 password.data[passlen]=0;    
648         }
649
650         p = smb_buf(inbuf) + passlen;
651         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
652
653         /*
654          * the service name can be either: \\server\share
655          * or share directly like on the DELL PowerVault 705
656          */
657         if (*path=='\\') {      
658                 q = strchr_m(path+2,'\\');
659                 if (!q) {
660                         END_PROFILE(SMBtconX);
661                         return(ERROR_DOS(ERRDOS,ERRnosuchshare));
662                 }
663                 fstrcpy(service,q+1);
664         }
665         else
666                 fstrcpy(service,path);
667                 
668         p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
669
670         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
671
672         conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
673         
674         data_blob_clear_free(&password);
675
676         if (!conn) {
677                 END_PROFILE(SMBtconX);
678                 return ERROR_NT(nt_status);
679         }
680
681         if ( IS_IPC(conn) )
682                 server_devicetype = "IPC";
683         else if ( IS_PRINT(conn) )
684                 server_devicetype = "LPT1:";
685         else 
686                 server_devicetype = "A:";
687
688         if (Protocol < PROTOCOL_NT1) {
689                 set_message(outbuf,2,0,True);
690                 p = smb_buf(outbuf);
691                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
692                                  STR_TERMINATE|STR_ASCII);
693                 set_message_end(outbuf,p);
694         } else {
695                 /* NT sets the fstype of IPC$ to the null string */
696                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
697                 
698                 set_message(outbuf,3,0,True);
699
700                 p = smb_buf(outbuf);
701                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
702                                  STR_TERMINATE|STR_ASCII);
703                 p += srvstr_push(outbuf, p, fstype, -1, 
704                                  STR_TERMINATE);
705                 
706                 set_message_end(outbuf,p);
707                 
708                 /* what does setting this bit do? It is set by NT4 and
709                    may affect the ability to autorun mounted cdroms */
710                 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
711                                 (lp_csc_policy(SNUM(conn)) << 2));
712                 
713                 init_dfsroot(conn, inbuf, outbuf);
714         }
715
716   
717         DEBUG(3,("tconX service=%s \n",
718                  service));
719   
720         /* set the incoming and outgoing tid to the just created one */
721         SSVAL(inbuf,smb_tid,conn->cnum);
722         SSVAL(outbuf,smb_tid,conn->cnum);
723
724         END_PROFILE(SMBtconX);
725         return chain_reply(inbuf,outbuf,length,bufsize);
726 }
727
728 /****************************************************************************
729  Reply to an unknown type.
730 ****************************************************************************/
731
732 int reply_unknown(char *inbuf,char *outbuf)
733 {
734         int type;
735         type = CVAL(inbuf,smb_com);
736   
737         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
738                  smb_fn_name(type), type, type));
739   
740         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
741 }
742
743 /****************************************************************************
744  Reply to an ioctl.
745  conn POINTER CAN BE NULL HERE !
746 ****************************************************************************/
747
748 int reply_ioctl(connection_struct *conn,
749                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
750 {
751         uint16 device     = SVAL(inbuf,smb_vwv1);
752         uint16 function   = SVAL(inbuf,smb_vwv2);
753         uint32 ioctl_code = (device << 16) + function;
754         int replysize, outsize;
755         char *p;
756         START_PROFILE(SMBioctl);
757
758         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
759
760         switch (ioctl_code) {
761             case IOCTL_QUERY_JOB_INFO:
762                 replysize = 32;
763                 break;
764             default:
765                 END_PROFILE(SMBioctl);
766                 return(ERROR_DOS(ERRSRV,ERRnosupport));
767         }
768
769         outsize = set_message(outbuf,8,replysize+1,True);
770         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
771         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
772         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
773         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
774
775         switch (ioctl_code) {
776                 case IOCTL_QUERY_JOB_INFO:                  
777                 {
778                         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
779                         if (!fsp) {
780                                 END_PROFILE(SMBioctl);
781                                 return(UNIXERROR(ERRDOS,ERRbadfid));
782                         }
783                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
784                         srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
785                         if (conn) {
786                                 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
787                         }
788                         break;
789                 }
790         }
791
792         END_PROFILE(SMBioctl);
793         return outsize;
794 }
795
796 /****************************************************************************
797  Reply to a chkpth.
798 ****************************************************************************/
799
800 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
801 {
802         int outsize = 0;
803         pstring name;
804         BOOL ok = False;
805         BOOL bad_path = False;
806         SMB_STRUCT_STAT sbuf;
807         NTSTATUS status;
808
809         START_PROFILE(SMBchkpth);
810
811         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
812         if (!NT_STATUS_IS_OK(status)) {
813                 END_PROFILE(SMBchkpth);
814
815                 /* Strange DOS error code semantics only for chkpth... */
816                 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
817                         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
818                                 /* We need to map to ERRbadpath */
819                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
820                         }
821                 }
822                 return ERROR_NT(status);
823         }
824
825         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
826
827         unix_convert(name,conn,0,&bad_path,&sbuf);
828         if (bad_path) {
829                 END_PROFILE(SMBchkpth);
830                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
831         }
832
833         if (check_name(name,conn)) {
834                 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
835                         if (!(ok = S_ISDIR(sbuf.st_mode))) {
836                                 END_PROFILE(SMBchkpth);
837                                 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
838                         }
839         }
840
841         if (!ok) {
842                 /* We special case this - as when a Windows machine
843                         is parsing a path is steps through the components
844                         one at a time - if a component fails it expects
845                         ERRbadpath, not ERRbadfile.
846                 */
847                 if(errno == ENOENT) {
848                         /*
849                          * Windows returns different error codes if
850                          * the parent directory is valid but not the
851                          * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
852                          * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
853                          * if the path is invalid. This is different from set_bad_path_error()
854                          * in the non-NT error case.
855                          */
856                         END_PROFILE(SMBchkpth);
857                         return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
858                 }
859
860                 END_PROFILE(SMBchkpth);
861                 return(UNIXERROR(ERRDOS,ERRbadpath));
862         }
863
864         outsize = set_message(outbuf,0,0,False);
865         DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
866
867         END_PROFILE(SMBchkpth);
868         return(outsize);
869 }
870
871 /****************************************************************************
872  Reply to a getatr.
873 ****************************************************************************/
874
875 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
876 {
877         pstring fname;
878         int outsize = 0;
879         SMB_STRUCT_STAT sbuf;
880         BOOL ok = False;
881         int mode=0;
882         SMB_OFF_T size=0;
883         time_t mtime=0;
884         BOOL bad_path = False;
885         char *p;
886         NTSTATUS status;
887
888         START_PROFILE(SMBgetatr);
889
890         p = smb_buf(inbuf) + 1;
891         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
892         if (!NT_STATUS_IS_OK(status)) {
893                 END_PROFILE(SMBgetatr);
894                 return ERROR_NT(status);
895         }
896
897         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
898   
899         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
900                 under WfWg - weird! */
901         if (! (*fname)) {
902                 mode = aHIDDEN | aDIR;
903                 if (!CAN_WRITE(conn))
904                         mode |= aRONLY;
905                 size = 0;
906                 mtime = 0;
907                 ok = True;
908         } else {
909                 unix_convert(fname,conn,0,&bad_path,&sbuf);
910                 if (bad_path) {
911                         END_PROFILE(SMBgetatr);
912                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
913                 }
914                 if (check_name(fname,conn)) {
915                         if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
916                                 mode = dos_mode(conn,fname,&sbuf);
917                                 size = sbuf.st_size;
918                                 mtime = sbuf.st_mtime;
919                                 if (mode & aDIR)
920                                         size = 0;
921                                 ok = True;
922                         } else {
923                                 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
924                         }
925                 }
926         }
927   
928         if (!ok) {
929                 END_PROFILE(SMBgetatr);
930                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
931         }
932  
933         outsize = set_message(outbuf,10,0,True);
934
935         SSVAL(outbuf,smb_vwv0,mode);
936         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
937                 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
938         } else {
939                 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
940         }
941         SIVAL(outbuf,smb_vwv3,(uint32)size);
942
943         if (Protocol >= PROTOCOL_NT1) {
944                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
945         }
946   
947         DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
948   
949         END_PROFILE(SMBgetatr);
950         return(outsize);
951 }
952
953 /****************************************************************************
954  Reply to a setatr.
955 ****************************************************************************/
956
957 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
958 {
959         pstring fname;
960         int outsize = 0;
961         BOOL ok=False;
962         int mode;
963         time_t mtime;
964         SMB_STRUCT_STAT sbuf;
965         BOOL bad_path = False;
966         char *p;
967         NTSTATUS status;
968
969         START_PROFILE(SMBsetatr);
970
971         p = smb_buf(inbuf) + 1;
972         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
973         if (!NT_STATUS_IS_OK(status)) {
974                 END_PROFILE(SMBsetatr);
975                 return ERROR_NT(status);
976         }
977
978         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
979   
980         unix_convert(fname,conn,0,&bad_path,&sbuf);
981         if (bad_path) {
982                 END_PROFILE(SMBsetatr);
983                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
984         }
985
986         mode = SVAL(inbuf,smb_vwv0);
987         mtime = srv_make_unix_date3(inbuf+smb_vwv1);
988   
989         if (mode != FILE_ATTRIBUTE_NORMAL) {
990                 if (VALID_STAT_OF_DIR(sbuf))
991                         mode |= aDIR;
992                 else
993                         mode &= ~aDIR;
994
995                 if (check_name(fname,conn)) {
996                         ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
997                 }
998         } else {
999                 ok = True;
1000         }
1001
1002         if (ok)
1003                 ok = set_filetime(conn,fname,mtime);
1004   
1005         if (!ok) {
1006                 END_PROFILE(SMBsetatr);
1007                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1008         }
1009  
1010         outsize = set_message(outbuf,0,0,False);
1011   
1012         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1013   
1014         END_PROFILE(SMBsetatr);
1015         return(outsize);
1016 }
1017
1018 /****************************************************************************
1019  Reply to a dskattr.
1020 ****************************************************************************/
1021
1022 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 {
1024         int outsize = 0;
1025         SMB_BIG_UINT dfree,dsize,bsize;
1026         START_PROFILE(SMBdskattr);
1027
1028         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1029                 END_PROFILE(SMBdskattr);
1030                 return(UNIXERROR(ERRHRD,ERRgeneral));
1031         }
1032   
1033         outsize = set_message(outbuf,5,0,True);
1034         
1035         if (Protocol <= PROTOCOL_LANMAN2) {
1036                 double total_space, free_space;
1037                 /* we need to scale this to a number that DOS6 can handle. We
1038                    use floating point so we can handle large drives on systems
1039                    that don't have 64 bit integers 
1040
1041                    we end up displaying a maximum of 2G to DOS systems
1042                 */
1043                 total_space = dsize * (double)bsize;
1044                 free_space = dfree * (double)bsize;
1045
1046                 dsize = (total_space+63*512) / (64*512);
1047                 dfree = (free_space+63*512) / (64*512);
1048                 
1049                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1050                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1051
1052                 SSVAL(outbuf,smb_vwv0,dsize);
1053                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1054                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1055                 SSVAL(outbuf,smb_vwv3,dfree);
1056         } else {
1057                 SSVAL(outbuf,smb_vwv0,dsize);
1058                 SSVAL(outbuf,smb_vwv1,bsize/512);
1059                 SSVAL(outbuf,smb_vwv2,512);
1060                 SSVAL(outbuf,smb_vwv3,dfree);
1061         }
1062
1063         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1064
1065         END_PROFILE(SMBdskattr);
1066         return(outsize);
1067 }
1068
1069 /****************************************************************************
1070  Reply to a search.
1071  Can be called from SMBsearch, SMBffirst or SMBfunique.
1072 ****************************************************************************/
1073
1074 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1075 {
1076         pstring mask;
1077         pstring directory;
1078         pstring fname;
1079         SMB_OFF_T size;
1080         uint32 mode;
1081         time_t date;
1082         uint32 dirtype;
1083         int outsize = 0;
1084         unsigned int numentries = 0;
1085         unsigned int maxentries = 0;
1086         BOOL finished = False;
1087         char *p;
1088         BOOL ok = False;
1089         int status_len;
1090         pstring path;
1091         char status[21];
1092         int dptr_num= -1;
1093         BOOL check_descend = False;
1094         BOOL expect_close = False;
1095         BOOL can_open = True;
1096         BOOL bad_path = False;
1097         NTSTATUS nt_status;
1098         BOOL mask_contains_wcard = False;
1099         BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1100
1101         START_PROFILE(SMBsearch);
1102
1103         if (lp_posix_pathnames()) {
1104                 END_PROFILE(SMBsearch);
1105                 return reply_unknown(inbuf, outbuf);
1106         }
1107
1108         *mask = *directory = *fname = 0;
1109
1110         /* If we were called as SMBffirst then we must expect close. */
1111         if(CVAL(inbuf,smb_com) == SMBffirst)
1112                 expect_close = True;
1113   
1114         outsize = set_message(outbuf,1,3,True);
1115         maxentries = SVAL(inbuf,smb_vwv0); 
1116         dirtype = SVAL(inbuf,smb_vwv1);
1117         p = smb_buf(inbuf) + 1;
1118         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1119         if (!NT_STATUS_IS_OK(nt_status)) {
1120                 END_PROFILE(SMBsearch);
1121                 return ERROR_NT(nt_status);
1122         }
1123
1124         RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1125   
1126         p++;
1127         status_len = SVAL(p, 0);
1128         p += 2;
1129   
1130         /* dirtype &= ~aDIR; */
1131
1132         if (status_len == 0) {
1133                 SMB_STRUCT_STAT sbuf;
1134                 pstring dir2;
1135
1136                 pstrcpy(directory,path);
1137                 pstrcpy(dir2,path);
1138                 unix_convert(directory,conn,0,&bad_path,&sbuf);
1139                 unix_format(dir2);
1140
1141                 if (!check_name(directory,conn))
1142                         can_open = False;
1143
1144                 p = strrchr_m(dir2,'/');
1145                 if (p == NULL) {
1146                         pstrcpy(mask,dir2);
1147                         *dir2 = 0;
1148                 } else {
1149                         *p = 0;
1150                         pstrcpy(mask,p+1);
1151                 }
1152
1153                 p = strrchr_m(directory,'/');
1154                 if (!p) 
1155                         *directory = 0;
1156                 else
1157                         *p = 0;
1158
1159                 if (strlen(directory) == 0)
1160                         pstrcpy(directory,".");
1161                 memset((char *)status,'\0',21);
1162                 SCVAL(status,0,(dirtype & 0x1F));
1163         } else {
1164                 int status_dirtype;
1165
1166                 memcpy(status,p,21);
1167                 status_dirtype = CVAL(status,0) & 0x1F;
1168                 if (status_dirtype != (dirtype & 0x1F))
1169                         dirtype = status_dirtype;
1170
1171                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1172                 if (!conn->dirptr)
1173                         goto SearchEmpty;
1174                 string_set(&conn->dirpath,dptr_path(dptr_num));
1175                 pstrcpy(mask, dptr_wcard(dptr_num));
1176         }
1177
1178         if (can_open) {
1179                 p = smb_buf(outbuf) + 3;
1180                 ok = True;
1181      
1182                 if (status_len == 0) {
1183                         dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1184                         if (dptr_num < 0) {
1185                                 if(dptr_num == -2) {
1186                                         END_PROFILE(SMBsearch);
1187                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1188                                 }
1189                                 END_PROFILE(SMBsearch);
1190                                 return ERROR_DOS(ERRDOS,ERRnofids);
1191                         }
1192                 } else {
1193                         dirtype = dptr_attr(dptr_num);
1194                 }
1195
1196                 DEBUG(4,("dptr_num is %d\n",dptr_num));
1197
1198                 if (ok) {
1199                         if ((dirtype&0x1F) == aVOLID) {   
1200                                 memcpy(p,status,21);
1201                                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1202                                                 0,aVOLID,0,!allow_long_path_components);
1203                                 dptr_fill(p+12,dptr_num);
1204                                 if (dptr_zero(p+12) && (status_len==0))
1205                                         numentries = 1;
1206                                 else
1207                                         numentries = 0;
1208                                 p += DIR_STRUCT_SIZE;
1209                         } else {
1210                                 unsigned int i;
1211                                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1212
1213                                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1214                                 conn->dirpath,lp_dontdescend(SNUM(conn))));
1215                                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1216                                         check_descend = True;
1217
1218                                 for (i=numentries;(i<maxentries) && !finished;i++) {
1219                                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1220                                         if (!finished) {
1221                                                 memcpy(p,status,21);
1222                                                 make_dir_struct(p,mask,fname,size, mode,date,
1223                                                                 !allow_long_path_components);
1224                                                 if (!dptr_fill(p+12,dptr_num)) {
1225                                                         break;
1226                                                 }
1227                                                 numentries++;
1228                                                 p += DIR_STRUCT_SIZE;
1229                                         }
1230                                 }
1231                         }
1232                 } /* if (ok ) */
1233         }
1234
1235
1236   SearchEmpty:
1237
1238         /* If we were called as SMBffirst with smb_search_id == NULL
1239                 and no entries were found then return error and close dirptr 
1240                 (X/Open spec) */
1241
1242         if (numentries == 0 || !ok) {
1243                 dptr_close(&dptr_num);
1244         } else if(ok && expect_close && status_len == 0) {
1245                 /* Close the dptr - we know it's gone */
1246                 dptr_close(&dptr_num);
1247         }
1248
1249         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1250         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1251                 dptr_close(&dptr_num);
1252         }
1253
1254         if ((numentries == 0) && !mask_contains_wcard) {
1255                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1256         }
1257
1258         SSVAL(outbuf,smb_vwv0,numentries);
1259         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1260         SCVAL(smb_buf(outbuf),0,5);
1261         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1262
1263         /* The replies here are never long name. */
1264         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1265         if (!allow_long_path_components) {
1266                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1267         }
1268
1269         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1270         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1271           
1272         outsize += DIR_STRUCT_SIZE*numentries;
1273         smb_setlen(outbuf,outsize - 4);
1274   
1275         if ((! *directory) && dptr_path(dptr_num))
1276                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1277
1278         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1279                 smb_fn_name(CVAL(inbuf,smb_com)), 
1280                 mask, directory, dirtype, numentries, maxentries ) );
1281
1282         END_PROFILE(SMBsearch);
1283         return(outsize);
1284 }
1285
1286 /****************************************************************************
1287  Reply to a fclose (stop directory search).
1288 ****************************************************************************/
1289
1290 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1291 {
1292         int outsize = 0;
1293         int status_len;
1294         pstring path;
1295         char status[21];
1296         int dptr_num= -2;
1297         char *p;
1298         NTSTATUS err;
1299         BOOL path_contains_wcard = False;
1300
1301         START_PROFILE(SMBfclose);
1302
1303         if (lp_posix_pathnames()) {
1304                 END_PROFILE(SMBfclose);
1305                 return reply_unknown(inbuf, outbuf);
1306         }
1307
1308         outsize = set_message(outbuf,1,0,True);
1309         p = smb_buf(inbuf) + 1;
1310         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1311         if (!NT_STATUS_IS_OK(err)) {
1312                 END_PROFILE(SMBfclose);
1313                 return ERROR_NT(err);
1314         }
1315         p++;
1316         status_len = SVAL(p,0);
1317         p += 2;
1318
1319         if (status_len == 0) {
1320                 END_PROFILE(SMBfclose);
1321                 return ERROR_DOS(ERRSRV,ERRsrverror);
1322         }
1323
1324         memcpy(status,p,21);
1325
1326         if(dptr_fetch(status+12,&dptr_num)) {
1327                 /*  Close the dptr - we know it's gone */
1328                 dptr_close(&dptr_num);
1329         }
1330
1331         SSVAL(outbuf,smb_vwv0,0);
1332
1333         DEBUG(3,("search close\n"));
1334
1335         END_PROFILE(SMBfclose);
1336         return(outsize);
1337 }
1338
1339 /****************************************************************************
1340  Reply to an open.
1341 ****************************************************************************/
1342
1343 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1344 {
1345         pstring fname;
1346         int outsize = 0;
1347         uint32 fattr=0;
1348         SMB_OFF_T size = 0;
1349         time_t mtime=0;
1350         int info;
1351         SMB_STRUCT_STAT sbuf;
1352         BOOL bad_path = False;
1353         files_struct *fsp;
1354         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1355         int deny_mode;
1356         uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1357         uint32 access_mask;
1358         uint32 share_mode;
1359         uint32 create_disposition;
1360         uint32 create_options = 0;
1361         NTSTATUS status;
1362         START_PROFILE(SMBopen);
1363  
1364         deny_mode = SVAL(inbuf,smb_vwv0);
1365
1366         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1367         if (!NT_STATUS_IS_OK(status)) {
1368                 END_PROFILE(SMBopen);
1369                 return ERROR_NT(status);
1370         }
1371
1372         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1373
1374         unix_convert(fname,conn,0,&bad_path,&sbuf);
1375         if (bad_path) {
1376                 END_PROFILE(SMBopen);
1377                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1378         }
1379     
1380         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1381                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1382                 END_PROFILE(SMBopen);
1383                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1384         }
1385
1386         status = open_file_ntcreate(conn,fname,&sbuf,
1387                         access_mask,
1388                         share_mode,
1389                         create_disposition,
1390                         create_options,
1391                         dos_attr,
1392                         oplock_request,
1393                         &info, &fsp);
1394
1395         if (!NT_STATUS_IS_OK(status)) {
1396                 END_PROFILE(SMBopen);
1397                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1398                         /* We have re-scheduled this call. */
1399                         return -1;
1400                 }
1401                 return ERROR_NT(status);
1402         }
1403
1404         size = sbuf.st_size;
1405         fattr = dos_mode(conn,fname,&sbuf);
1406         mtime = sbuf.st_mtime;
1407
1408         if (fattr & aDIR) {
1409                 DEBUG(3,("attempt to open a directory %s\n",fname));
1410                 close_file(fsp,ERROR_CLOSE);
1411                 END_PROFILE(SMBopen);
1412                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1413         }
1414   
1415         outsize = set_message(outbuf,7,0,True);
1416         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1417         SSVAL(outbuf,smb_vwv1,fattr);
1418         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1419                 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1420         } else {
1421                 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1422         }
1423         SIVAL(outbuf,smb_vwv4,(uint32)size);
1424         SSVAL(outbuf,smb_vwv6,deny_mode);
1425
1426         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1427                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1428         }
1429     
1430         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1431                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1432         }
1433         END_PROFILE(SMBopen);
1434         return(outsize);
1435 }
1436
1437 /****************************************************************************
1438  Reply to an open and X.
1439 ****************************************************************************/
1440
1441 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1442 {
1443         pstring fname;
1444         uint16 open_flags = SVAL(inbuf,smb_vwv2);
1445         int deny_mode = SVAL(inbuf,smb_vwv3);
1446         uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1447         /* Breakout the oplock request bits so we can set the
1448                 reply bits separately. */
1449         int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1450         int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1451         int oplock_request = ex_oplock_request | core_oplock_request;
1452 #if 0
1453         int smb_sattr = SVAL(inbuf,smb_vwv4); 
1454         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1455 #endif
1456         int smb_ofun = SVAL(inbuf,smb_vwv8);
1457         SMB_OFF_T size=0;
1458         uint32 fattr=0;
1459         int mtime=0;
1460         SMB_STRUCT_STAT sbuf;
1461         int smb_action = 0;
1462         BOOL bad_path = False;
1463         files_struct *fsp;
1464         NTSTATUS status;
1465         SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1466         ssize_t retval = -1;
1467         uint32 access_mask;
1468         uint32 share_mode;
1469         uint32 create_disposition;
1470         uint32 create_options = 0;
1471
1472         START_PROFILE(SMBopenX);
1473
1474         /* If it's an IPC, pass off the pipe handler. */
1475         if (IS_IPC(conn)) {
1476                 if (lp_nt_pipe_support()) {
1477                         END_PROFILE(SMBopenX);
1478                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1479                 } else {
1480                         END_PROFILE(SMBopenX);
1481                         return ERROR_DOS(ERRSRV,ERRaccess);
1482                 }
1483         }
1484
1485         /* XXXX we need to handle passed times, sattr and flags */
1486         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1487         if (!NT_STATUS_IS_OK(status)) {
1488                 END_PROFILE(SMBopenX);
1489                 return ERROR_NT(status);
1490         }
1491
1492         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1493
1494         unix_convert(fname,conn,0,&bad_path,&sbuf);
1495         if (bad_path) {
1496                 END_PROFILE(SMBopenX);
1497                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1498         }
1499
1500         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1501                                 &access_mask,
1502                                 &share_mode,
1503                                 &create_disposition,
1504                                 &create_options)) {
1505                 END_PROFILE(SMBopenX);
1506                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1507         }
1508
1509         status = open_file_ntcreate(conn,fname,&sbuf,
1510                         access_mask,
1511                         share_mode,
1512                         create_disposition,
1513                         create_options,
1514                         smb_attr,
1515                         oplock_request,
1516                         &smb_action, &fsp);
1517       
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 END_PROFILE(SMBopenX);
1520                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1521                         /* We have re-scheduled this call. */
1522                         return -1;
1523                 }
1524                 return ERROR_NT(status);
1525         }
1526
1527         size = sbuf.st_size;
1528
1529         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1530            if the file is truncated or created. */
1531         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1532                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1533                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1534                         close_file(fsp,ERROR_CLOSE);
1535                         END_PROFILE(SMBopenX);
1536                         return ERROR_NT(NT_STATUS_DISK_FULL);
1537                 }
1538                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1539                 if (retval < 0) {
1540                         close_file(fsp,ERROR_CLOSE);
1541                         END_PROFILE(SMBopenX);
1542                         return ERROR_NT(NT_STATUS_DISK_FULL);
1543                 }
1544                 size = get_allocation_size(conn,fsp,&sbuf);
1545         }
1546
1547         fattr = dos_mode(conn,fname,&sbuf);
1548         mtime = sbuf.st_mtime;
1549         if (fattr & aDIR) {
1550                 close_file(fsp,ERROR_CLOSE);
1551                 END_PROFILE(SMBopenX);
1552                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1553         }
1554
1555         /* If the caller set the extended oplock request bit
1556                 and we granted one (by whatever means) - set the
1557                 correct bit for extended oplock reply.
1558         */
1559
1560         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1561                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1562         }
1563
1564         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1565                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1566         }
1567
1568         /* If the caller set the core oplock request bit
1569                 and we granted one (by whatever means) - set the
1570                 correct bit for core oplock reply.
1571         */
1572
1573         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1574                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1575         }
1576
1577         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1578                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1579         }
1580
1581         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1582                 set_message(outbuf,19,0,True);
1583         } else {
1584                 set_message(outbuf,15,0,True);
1585         }
1586         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1587         SSVAL(outbuf,smb_vwv3,fattr);
1588         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1589                 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1590         } else {
1591                 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1592         }
1593         SIVAL(outbuf,smb_vwv6,(uint32)size);
1594         SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1595         SSVAL(outbuf,smb_vwv11,smb_action);
1596
1597         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1598                 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1599         }
1600
1601         END_PROFILE(SMBopenX);
1602         return chain_reply(inbuf,outbuf,length,bufsize);
1603 }
1604
1605 /****************************************************************************
1606  Reply to a SMBulogoffX.
1607  conn POINTER CAN BE NULL HERE !
1608 ****************************************************************************/
1609
1610 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1611 {
1612         uint16 vuid = SVAL(inbuf,smb_uid);
1613         user_struct *vuser = get_valid_user_struct(vuid);
1614         START_PROFILE(SMBulogoffX);
1615
1616         if(vuser == 0)
1617                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1618
1619         /* in user level security we are supposed to close any files
1620                 open by this user */
1621         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1622                 file_close_user(vuid);
1623
1624         invalidate_vuid(vuid);
1625
1626         set_message(outbuf,2,0,True);
1627
1628         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1629
1630         END_PROFILE(SMBulogoffX);
1631         return chain_reply(inbuf,outbuf,length,bufsize);
1632 }
1633
1634 /****************************************************************************
1635  Reply to a mknew or a create.
1636 ****************************************************************************/
1637
1638 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1639 {
1640         pstring fname;
1641         int com;
1642         int outsize = 0;
1643         uint32 fattr = SVAL(inbuf,smb_vwv0);
1644         BOOL bad_path = False;
1645         files_struct *fsp;
1646         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1647         SMB_STRUCT_STAT sbuf;
1648         NTSTATUS status;
1649         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1650         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1651         uint32 create_disposition;
1652         uint32 create_options = 0;
1653
1654         START_PROFILE(SMBcreate);
1655  
1656         com = SVAL(inbuf,smb_com);
1657
1658         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1659         if (!NT_STATUS_IS_OK(status)) {
1660                 END_PROFILE(SMBcreate);
1661                 return ERROR_NT(status);
1662         }
1663
1664         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1665
1666         unix_convert(fname,conn,0,&bad_path,&sbuf);
1667         if (bad_path) {
1668                 END_PROFILE(SMBcreate);
1669                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1670         }
1671
1672         if (fattr & aVOLID) {
1673                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1674         }
1675
1676         if(com == SMBmknew) {
1677                 /* We should fail if file exists. */
1678                 create_disposition = FILE_CREATE;
1679         } else {
1680                 /* Create if file doesn't exist, truncate if it does. */
1681                 create_disposition = FILE_OVERWRITE_IF;
1682         }
1683
1684         /* Open file using ntcreate. */
1685         status = open_file_ntcreate(conn,fname,&sbuf,
1686                                 access_mask,
1687                                 share_mode,
1688                                 create_disposition,
1689                                 create_options,
1690                                 fattr,
1691                                 oplock_request,
1692                                 NULL, &fsp);
1693   
1694         if (!NT_STATUS_IS_OK(status)) {
1695                 END_PROFILE(SMBcreate);
1696                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1697                         /* We have re-scheduled this call. */
1698                         return -1;
1699                 }
1700                 return ERROR_NT(status);
1701         }
1702  
1703         outsize = set_message(outbuf,1,0,True);
1704         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1705
1706         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1707                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1708         }
1709  
1710         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1711                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1712         }
1713  
1714         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1715         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1716
1717         END_PROFILE(SMBcreate);
1718         return(outsize);
1719 }
1720
1721 /****************************************************************************
1722  Reply to a create temporary file.
1723 ****************************************************************************/
1724
1725 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1726 {
1727         pstring fname;
1728         int outsize = 0;
1729         uint32 fattr = SVAL(inbuf,smb_vwv0);
1730         BOOL bad_path = False;
1731         files_struct *fsp;
1732         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1733         int tmpfd;
1734         SMB_STRUCT_STAT sbuf;
1735         char *p, *s;
1736         NTSTATUS status;
1737         unsigned int namelen;
1738
1739         START_PROFILE(SMBctemp);
1740
1741         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 END_PROFILE(SMBctemp);
1744                 return ERROR_NT(status);
1745         }
1746         if (*fname) {
1747                 pstrcat(fname,"/TMXXXXXX");
1748         } else {
1749                 pstrcat(fname,"TMXXXXXX");
1750         }
1751
1752         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1753
1754         unix_convert(fname,conn,0,&bad_path,&sbuf);
1755         if (bad_path) {
1756                 END_PROFILE(SMBctemp);
1757                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1758         }
1759   
1760         tmpfd = smb_mkstemp(fname);
1761         if (tmpfd == -1) {
1762                 END_PROFILE(SMBctemp);
1763                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1764         }
1765
1766         SMB_VFS_STAT(conn,fname,&sbuf);
1767
1768         /* We should fail if file does not exist. */
1769         status = open_file_ntcreate(conn,fname,&sbuf,
1770                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1771                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1772                                 FILE_OPEN,
1773                                 0,
1774                                 fattr,
1775                                 oplock_request,
1776                                 NULL, &fsp);
1777
1778         /* close fd from smb_mkstemp() */
1779         close(tmpfd);
1780
1781         if (!NT_STATUS_IS_OK(status)) {
1782                 END_PROFILE(SMBctemp);
1783                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1784                         /* We have re-scheduled this call. */
1785                         return -1;
1786                 }
1787                 return ERROR_NT(status);
1788         }
1789
1790         outsize = set_message(outbuf,1,0,True);
1791         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1792
1793         /* the returned filename is relative to the directory */
1794         s = strrchr_m(fname, '/');
1795         if (!s) {
1796                 s = fname;
1797         } else {
1798                 s++;
1799         }
1800
1801         p = smb_buf(outbuf);
1802 #if 0
1803         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1804            thing in the byte section. JRA */
1805         SSVALS(p, 0, -1); /* what is this? not in spec */
1806 #endif
1807         namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1808         p += namelen;
1809         outsize = set_message_end(outbuf, p);
1810
1811         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1812                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1813         }
1814   
1815         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1816                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1817         }
1818
1819         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1820         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1821                         (unsigned int)sbuf.st_mode ) );
1822
1823         END_PROFILE(SMBctemp);
1824         return(outsize);
1825 }
1826
1827 /*******************************************************************
1828  Check if a user is allowed to rename a file.
1829 ********************************************************************/
1830
1831 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1832 {
1833         files_struct *fsp;
1834         uint32 fmode;
1835         NTSTATUS status;
1836
1837         if (!CAN_WRITE(conn)) {
1838                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1839         }
1840
1841         fmode = dos_mode(conn,fname,pst);
1842         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1843                 return NT_STATUS_NO_SUCH_FILE;
1844         }
1845
1846         if (S_ISDIR(pst->st_mode)) {
1847                 return NT_STATUS_OK;
1848         }
1849
1850         status = open_file_ntcreate(conn, fname, pst,
1851                                 DELETE_ACCESS,
1852                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1853                                 FILE_OPEN,
1854                                 0,
1855                                 FILE_ATTRIBUTE_NORMAL,
1856                                 0,
1857                                 NULL, &fsp);
1858
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 return NT_STATUS_ACCESS_DENIED;
1861         }
1862         close_file(fsp,NORMAL_CLOSE);
1863         return NT_STATUS_OK;
1864 }
1865
1866 /*******************************************************************
1867  Check if a user is allowed to delete a file.
1868 ********************************************************************/
1869
1870 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1871 {
1872         SMB_STRUCT_STAT sbuf;
1873         uint32 fattr;
1874         files_struct *fsp;
1875         NTSTATUS status;
1876
1877         DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1878
1879         if (!CAN_WRITE(conn)) {
1880                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1881         }
1882
1883         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1884                 if(errno == ENOENT) {
1885                         if (bad_path) {
1886                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1887                         } else {
1888                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1889                         }
1890                 }
1891                 return map_nt_error_from_unix(errno);
1892         }
1893
1894         fattr = dos_mode(conn,fname,&sbuf);
1895
1896         /* Can't delete a directory. */
1897         if (fattr & aDIR) {
1898                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1899         }
1900
1901 #if 0 /* JRATEST */
1902         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1903                 return NT_STATUS_OBJECT_NAME_INVALID;
1904 #endif /* JRATEST */
1905
1906         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1907
1908           On a Windows share, a file with read-only dosmode can be opened with
1909           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1910           fails with NT_STATUS_CANNOT_DELETE error.
1911
1912           This semantic causes a problem that a user can not
1913           rename a file with read-only dosmode on a Samba share
1914           from a Windows command prompt (i.e. cmd.exe, but can rename
1915           from Windows Explorer).
1916         */
1917
1918         if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
1919                 if (fattr & aRONLY) {
1920                         return NT_STATUS_CANNOT_DELETE;
1921                 }
1922         }
1923         if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1924                 return NT_STATUS_NO_SUCH_FILE;
1925         }
1926
1927         if (check_is_at_open) {
1928                 if (!can_delete_file_in_directory(conn, fname)) {
1929                         return NT_STATUS_ACCESS_DENIED;
1930                 }
1931         } else {
1932                 /* On open checks the open itself will check the share mode, so
1933                    don't do it here as we'll get it wrong. */
1934
1935                 status = open_file_ntcreate(conn, fname, &sbuf,
1936                                         DELETE_ACCESS,
1937                                         FILE_SHARE_NONE,
1938                                         FILE_OPEN,
1939                                         0,
1940                                         FILE_ATTRIBUTE_NORMAL,
1941                                         0,
1942                                         NULL, &fsp);
1943
1944                 if (!NT_STATUS_IS_OK(status)) {
1945                         return status;
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,conn->params))
1992                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
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,False);
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,(uint32)SVAL(inbuf,smb_pid),(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         START_PROFILE(SMBlockread);
2375
2376         CHECK_FSP(fsp,conn);
2377         if (!CHECK_READ(fsp,inbuf)) {
2378                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2379         }
2380
2381         release_level_2_oplocks_on_change(fsp);
2382
2383         numtoread = SVAL(inbuf,smb_vwv1);
2384         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2385   
2386         outsize = set_message(outbuf,5,3,True);
2387         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2388         data = smb_buf(outbuf) + 3;
2389         
2390         /*
2391          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2392          * protocol request that predates the read/write lock concept. 
2393          * Thus instead of asking for a read lock here we need to ask
2394          * for a write lock. JRA.
2395          * Note that the requested lock size is unaffected by max_recv.
2396          */
2397         
2398         status = do_lock(fsp,
2399                         (uint32)SVAL(inbuf,smb_pid), 
2400                         (SMB_BIG_UINT)numtoread,
2401                         (SMB_BIG_UINT)startpos,
2402                         WRITE_LOCK,
2403                         WINDOWS_LOCK,
2404                         0 /* zero timeout. */);
2405
2406         if (NT_STATUS_V(status)) {
2407 #if 0
2408                 /*
2409                  * We used to make lockread a blocking lock. It turns out
2410                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2411                  * tester. JRA.
2412                  */
2413
2414                 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2415                         /*
2416                          * A blocking lock was requested. Package up
2417                          * this smb into a queued request and push it
2418                          * onto the blocking lock queue.
2419                          */
2420                         if(push_blocking_lock_request(inbuf, length,
2421                                         fsp,
2422                                         -1,
2423                                         0,
2424                                         SVAL(inbuf,smb_pid),
2425                                         WRITE_LOCK,
2426                                         WINDOWS_LOCK,
2427                                         (SMB_BIG_UINT)startpos,
2428                                         (SMB_BIG_UINT)numtoread)) {
2429                                 END_PROFILE(SMBlockread);
2430                                 return -1;
2431                         }
2432                 }
2433 #endif
2434                 END_PROFILE(SMBlockread);
2435                 return ERROR_NT(status);
2436         }
2437
2438         /*
2439          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2440          */
2441
2442         if (numtoread > max_recv) {
2443                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2444 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2445                         (unsigned int)numtoread, (unsigned int)max_recv ));
2446                 numtoread = MIN(numtoread,max_recv);
2447         }
2448         nread = read_file(fsp,data,startpos,numtoread);
2449
2450         if (nread < 0) {
2451                 END_PROFILE(SMBlockread);
2452                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2453         }
2454         
2455         outsize += nread;
2456         SSVAL(outbuf,smb_vwv0,nread);
2457         SSVAL(outbuf,smb_vwv5,nread+3);
2458         SSVAL(smb_buf(outbuf),1,nread);
2459         
2460         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2461                  fsp->fnum, (int)numtoread, (int)nread));
2462
2463         END_PROFILE(SMBlockread);
2464         return(outsize);
2465 }
2466
2467 #undef DBGC_CLASS
2468 #define DBGC_CLASS DBGC_ALL
2469
2470 /****************************************************************************
2471  Reply to a read.
2472 ****************************************************************************/
2473
2474 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2475 {
2476         size_t numtoread;
2477         ssize_t nread = 0;
2478         char *data;
2479         SMB_OFF_T startpos;
2480         int outsize = 0;
2481         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2482         START_PROFILE(SMBread);
2483
2484         CHECK_FSP(fsp,conn);
2485         if (!CHECK_READ(fsp,inbuf)) {
2486                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2487         }
2488
2489         numtoread = SVAL(inbuf,smb_vwv1);
2490         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2491
2492         outsize = set_message(outbuf,5,3,True);
2493         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2494         /*
2495          * The requested read size cannot be greater than max_recv. JRA.
2496          */
2497         if (numtoread > max_recv) {
2498                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2499 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2500                         (unsigned int)numtoread, (unsigned int)max_recv ));
2501                 numtoread = MIN(numtoread,max_recv);
2502         }
2503
2504         data = smb_buf(outbuf) + 3;
2505   
2506         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2507                 END_PROFILE(SMBread);
2508                 return ERROR_DOS(ERRDOS,ERRlock);
2509         }
2510
2511         if (numtoread > 0)
2512                 nread = read_file(fsp,data,startpos,numtoread);
2513
2514         if (nread < 0) {
2515                 END_PROFILE(SMBread);
2516                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2517         }
2518   
2519         outsize += nread;
2520         SSVAL(outbuf,smb_vwv0,nread);
2521         SSVAL(outbuf,smb_vwv5,nread+3);
2522         SCVAL(smb_buf(outbuf),0,1);
2523         SSVAL(smb_buf(outbuf),1,nread);
2524   
2525         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2526                 fsp->fnum, (int)numtoread, (int)nread ) );
2527
2528         END_PROFILE(SMBread);
2529         return(outsize);
2530 }
2531
2532 /****************************************************************************
2533  Reply to a read and X - possibly using sendfile.
2534 ****************************************************************************/
2535
2536 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2537                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2538 {
2539         int outsize = 0;
2540         ssize_t nread = -1;
2541         char *data = smb_buf(outbuf);
2542
2543 #if defined(WITH_SENDFILE)
2544         /*
2545          * We can only use sendfile on a non-chained packet 
2546          * but we can use on a non-oplocked file. tridge proved this
2547          * on a train in Germany :-). JRA.
2548          */
2549
2550         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2551             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2552                 SMB_STRUCT_STAT sbuf;
2553                 DATA_BLOB header;
2554
2555                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2556                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2557
2558                 if (startpos > sbuf.st_size)
2559                         goto normal_read;
2560
2561                 if (smb_maxcnt > (sbuf.st_size - startpos))
2562                         smb_maxcnt = (sbuf.st_size - startpos);
2563
2564                 if (smb_maxcnt == 0)
2565                         goto normal_read;
2566
2567                 /* 
2568                  * Set up the packet header before send. We
2569                  * assume here the sendfile will work (get the
2570                  * correct amount of data).
2571                  */
2572
2573                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2574                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2575                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2576                 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2577                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2578                 SCVAL(outbuf,smb_vwv0,0xFF);
2579                 set_message(outbuf,12,smb_maxcnt,False);
2580                 header.data = (uint8 *)outbuf;
2581                 header.length = data - outbuf;
2582                 header.free = NULL;
2583
2584                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2585                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2586                         if (errno == ENOSYS) {
2587                                 goto normal_read;
2588                         }
2589
2590                         /*
2591                          * Special hack for broken Linux with no working sendfile. If we
2592                          * return EINTR we sent the header but not the rest of the data.
2593                          * Fake this up by doing read/write calls.
2594                          */
2595
2596                         if (errno == EINTR) {
2597                                 /* Ensure we don't do this again. */
2598                                 set_use_sendfile(SNUM(conn), False);
2599                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2600
2601                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2602                                                         len_outbuf - (data-outbuf))) == -1) {
2603                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2604                                                 fsp->fsp_name, strerror(errno) ));
2605                                         exit_server("send_file_readX: fake_sendfile failed");
2606                                 }
2607                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2608                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2609                                 /* Returning -1 here means successful sendfile. */
2610                                 return -1;
2611                         }
2612
2613                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2614                                 fsp->fsp_name, strerror(errno) ));
2615                         exit_server("send_file_readX sendfile failed");
2616                 }
2617
2618                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2619                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2620                 /* Returning -1 here means successful sendfile. */
2621                 return -1;
2622         }
2623
2624   normal_read:
2625
2626 #endif
2627
2628         nread = read_file(fsp,data,startpos,smb_maxcnt);
2629   
2630         if (nread < 0) {
2631                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2632         }
2633
2634         outsize = set_message(outbuf,12,nread,False);
2635         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2636         SSVAL(outbuf,smb_vwv5,nread);
2637         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2638         SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2639         SSVAL(smb_buf(outbuf),-2,nread);
2640   
2641         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2642                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2643
2644         /* Returning the number of bytes we want to send back - including header. */
2645         return outsize;
2646 }
2647
2648 /****************************************************************************
2649  Reply to a read and X.
2650 ****************************************************************************/
2651
2652 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2653 {
2654         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2655         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2656         ssize_t nread = -1;
2657         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2658 #if 0
2659         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2660 #endif
2661
2662         START_PROFILE(SMBreadX);
2663
2664         /* If it's an IPC, pass off the pipe handler. */
2665         if (IS_IPC(conn)) {
2666                 END_PROFILE(SMBreadX);
2667                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2668         }
2669
2670         CHECK_FSP(fsp,conn);
2671         if (!CHECK_READ(fsp,inbuf)) {
2672                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2673         }
2674
2675         set_message(outbuf,12,0,True);
2676
2677         if (global_client_caps & CAP_LARGE_READX) {
2678                 if (SVAL(inbuf,smb_vwv7) == 1) {
2679                         smb_maxcnt |= (1<<16);
2680                 }
2681                 if (smb_maxcnt > BUFFER_SIZE) {
2682                         DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2683                                 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2684                         END_PROFILE(SMBreadX);
2685                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2686                 }
2687         }
2688
2689         if(CVAL(inbuf,smb_wct) == 12) {
2690 #ifdef LARGE_SMB_OFF_T
2691                 /*
2692                  * This is a large offset (64 bit) read.
2693                  */
2694                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2695
2696 #else /* !LARGE_SMB_OFF_T */
2697
2698                 /*
2699                  * Ensure we haven't been sent a >32 bit offset.
2700                  */
2701
2702                 if(IVAL(inbuf,smb_vwv10) != 0) {
2703                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2704 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2705                         END_PROFILE(SMBreadX);
2706                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2707                 }
2708
2709 #endif /* LARGE_SMB_OFF_T */
2710
2711         }
2712
2713         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2714                 END_PROFILE(SMBreadX);
2715                 return ERROR_DOS(ERRDOS,ERRlock);
2716         }
2717
2718         if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2719                 END_PROFILE(SMBreadX);
2720                 return -1;
2721         }
2722
2723         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2724         if (nread != -1)
2725                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2726
2727         END_PROFILE(SMBreadX);
2728         return nread;
2729 }
2730
2731 /****************************************************************************
2732  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2733 ****************************************************************************/
2734
2735 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2736 {
2737         ssize_t nwritten=0;
2738         ssize_t total_written=0;
2739         size_t numtowrite=0;
2740         size_t tcount;
2741         SMB_OFF_T startpos;
2742         char *data=NULL;
2743         BOOL write_through;
2744         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2745         int outsize = 0;
2746         START_PROFILE(SMBwritebraw);
2747
2748         if (srv_is_signing_active()) {
2749                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2750         }
2751
2752         CHECK_FSP(fsp,conn);
2753         if (!CHECK_WRITE(fsp)) {
2754                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2755         }
2756   
2757         tcount = IVAL(inbuf,smb_vwv1);
2758         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2759         write_through = BITSETW(inbuf+smb_vwv7,0);
2760
2761         /* We have to deal with slightly different formats depending
2762                 on whether we are using the core+ or lanman1.0 protocol */
2763
2764         if(Protocol <= PROTOCOL_COREPLUS) {
2765                 numtowrite = SVAL(smb_buf(inbuf),-2);
2766                 data = smb_buf(inbuf);
2767         } else {
2768                 numtowrite = SVAL(inbuf,smb_vwv10);
2769                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2770         }
2771
2772         /* force the error type */
2773         SCVAL(inbuf,smb_com,SMBwritec);
2774         SCVAL(outbuf,smb_com,SMBwritec);
2775
2776         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2777                 END_PROFILE(SMBwritebraw);
2778                 return(ERROR_DOS(ERRDOS,ERRlock));
2779         }
2780
2781         if (numtowrite>0)
2782                 nwritten = write_file(fsp,data,startpos,numtowrite);
2783   
2784         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2785                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2786
2787         if (nwritten < (ssize_t)numtowrite)  {
2788                 END_PROFILE(SMBwritebraw);
2789                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2790         }
2791
2792         total_written = nwritten;
2793
2794         /* Return a message to the redirector to tell it to send more bytes */
2795         SCVAL(outbuf,smb_com,SMBwritebraw);
2796         SSVALS(outbuf,smb_vwv0,-1);
2797         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2798         show_msg(outbuf);
2799         if (!send_smb(smbd_server_fd(),outbuf))
2800                 exit_server("reply_writebraw: send_smb failed.");
2801   
2802         /* Now read the raw data into the buffer and write it */
2803         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2804                 exit_server("secondary writebraw failed");
2805         }
2806   
2807         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2808         numtowrite = smb_len(inbuf);
2809
2810         /* Set up outbuf to return the correct return */
2811         outsize = set_message(outbuf,1,0,True);
2812         SCVAL(outbuf,smb_com,SMBwritec);
2813
2814         if (numtowrite != 0) {
2815
2816                 if (numtowrite > BUFFER_SIZE) {
2817                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2818                                 (unsigned int)numtowrite ));
2819                         exit_server("secondary writebraw failed");
2820                 }
2821
2822                 if (tcount > nwritten+numtowrite) {
2823                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2824                                 (int)tcount,(int)nwritten,(int)numtowrite));
2825                 }
2826
2827                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2828                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2829                                 strerror(errno) ));
2830                         exit_server("secondary writebraw failed");
2831                 }
2832
2833                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2834
2835                 if (nwritten < (ssize_t)numtowrite) {
2836                         SCVAL(outbuf,smb_rcls,ERRHRD);
2837                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2838                 }
2839
2840                 if (nwritten > 0)
2841                         total_written += nwritten;
2842         }
2843  
2844         SSVAL(outbuf,smb_vwv0,total_written);
2845
2846         sync_file(conn, fsp, write_through);
2847
2848         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2849                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2850
2851         /* we won't return a status if write through is not selected - this follows what WfWg does */
2852         END_PROFILE(SMBwritebraw);
2853         if (!write_through && total_written==tcount) {
2854
2855 #if RABBIT_PELLET_FIX
2856                 /*
2857                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2858                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2859                  */
2860                 if (!send_keepalive(smbd_server_fd()))
2861                         exit_server("reply_writebraw: send of keepalive failed");
2862 #endif
2863                 return(-1);
2864         }
2865
2866         return(outsize);
2867 }
2868
2869 #undef DBGC_CLASS
2870 #define DBGC_CLASS DBGC_LOCKING
2871
2872 /****************************************************************************
2873  Reply to a writeunlock (core+).
2874 ****************************************************************************/
2875
2876 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2877                       int size, int dum_buffsize)
2878 {
2879         ssize_t nwritten = -1;
2880         size_t numtowrite;
2881         SMB_OFF_T startpos;
2882         char *data;
2883         NTSTATUS status = NT_STATUS_OK;
2884         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2885         int outsize = 0;
2886         START_PROFILE(SMBwriteunlock);
2887         
2888         CHECK_FSP(fsp,conn);
2889         if (!CHECK_WRITE(fsp)) {
2890                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2891         }
2892
2893         numtowrite = SVAL(inbuf,smb_vwv1);
2894         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2895         data = smb_buf(inbuf) + 3;
2896   
2897         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2898                 END_PROFILE(SMBwriteunlock);
2899                 return ERROR_DOS(ERRDOS,ERRlock);
2900         }
2901
2902         /* The special X/Open SMB protocol handling of
2903            zero length writes is *NOT* done for
2904            this call */
2905         if(numtowrite == 0) {
2906                 nwritten = 0;
2907         } else {
2908                 nwritten = write_file(fsp,data,startpos,numtowrite);
2909         }
2910   
2911         sync_file(conn, fsp, False /* write through */);
2912
2913         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2914                 END_PROFILE(SMBwriteunlock);
2915                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2916         }
2917
2918         if (numtowrite) {
2919                 status = do_unlock(fsp,
2920                                 (uint32)SVAL(inbuf,smb_pid),
2921                                 (SMB_BIG_UINT)numtowrite, 
2922                                 (SMB_BIG_UINT)startpos,
2923                                 WINDOWS_LOCK);
2924
2925                 if (NT_STATUS_V(status)) {
2926                         END_PROFILE(SMBwriteunlock);
2927                         return ERROR_NT(status);
2928                 }
2929         }
2930         
2931         outsize = set_message(outbuf,1,0,True);
2932         
2933         SSVAL(outbuf,smb_vwv0,nwritten);
2934         
2935         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2936                  fsp->fnum, (int)numtowrite, (int)nwritten));
2937         
2938         END_PROFILE(SMBwriteunlock);
2939         return outsize;
2940 }
2941
2942 #undef DBGC_CLASS
2943 #define DBGC_CLASS DBGC_ALL
2944
2945 /****************************************************************************
2946  Reply to a write.
2947 ****************************************************************************/
2948
2949 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2950 {
2951         size_t numtowrite;
2952         ssize_t nwritten = -1;
2953         SMB_OFF_T startpos;
2954         char *data;
2955         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2956         int outsize = 0;
2957         START_PROFILE(SMBwrite);
2958
2959         /* If it's an IPC, pass off the pipe handler. */
2960         if (IS_IPC(conn)) {
2961                 END_PROFILE(SMBwrite);
2962                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2963         }
2964
2965         CHECK_FSP(fsp,conn);
2966         if (!CHECK_WRITE(fsp)) {
2967                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2968         }
2969
2970         numtowrite = SVAL(inbuf,smb_vwv1);
2971         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2972         data = smb_buf(inbuf) + 3;
2973   
2974         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2975                 END_PROFILE(SMBwrite);
2976                 return ERROR_DOS(ERRDOS,ERRlock);
2977         }
2978
2979         /*
2980          * X/Open SMB protocol says that if smb_vwv1 is
2981          * zero then the file size should be extended or
2982          * truncated to the size given in smb_vwv[2-3].
2983          */
2984
2985         if(numtowrite == 0) {
2986                 /*
2987                  * This is actually an allocate call, and set EOF. JRA.
2988                  */
2989                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2990                 if (nwritten < 0) {
2991                         END_PROFILE(SMBwrite);
2992                         return ERROR_NT(NT_STATUS_DISK_FULL);
2993                 }
2994                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2995                 if (nwritten < 0) {
2996                         END_PROFILE(SMBwrite);
2997                         return ERROR_NT(NT_STATUS_DISK_FULL);
2998                 }
2999         } else
3000                 nwritten = write_file(fsp,data,startpos,numtowrite);
3001   
3002         sync_file(conn, fsp, False);
3003
3004         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3005                 END_PROFILE(SMBwrite);
3006                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3007         }
3008
3009         outsize = set_message(outbuf,1,0,True);
3010   
3011         SSVAL(outbuf,smb_vwv0,nwritten);
3012
3013         if (nwritten < (ssize_t)numtowrite) {
3014                 SCVAL(outbuf,smb_rcls,ERRHRD);
3015                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3016         }
3017   
3018         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3019
3020         END_PROFILE(SMBwrite);
3021         return(outsize);
3022 }
3023
3024 /****************************************************************************
3025  Reply to a write and X.
3026 ****************************************************************************/
3027
3028 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3029 {
3030         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3031         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3032         size_t numtowrite = SVAL(inbuf,smb_vwv10);
3033         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3034         ssize_t nwritten = -1;
3035         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3036         unsigned int smblen = smb_len(inbuf);
3037         char *data;
3038         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3039         START_PROFILE(SMBwriteX);
3040
3041         /* If it's an IPC, pass off the pipe handler. */
3042         if (IS_IPC(conn)) {
3043                 END_PROFILE(SMBwriteX);
3044                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3045         }
3046
3047         CHECK_FSP(fsp,conn);
3048         if (!CHECK_WRITE(fsp)) {
3049                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3050         }
3051
3052         set_message(outbuf,6,0,True);
3053   
3054         /* Deal with possible LARGE_WRITEX */
3055         if (large_writeX) {
3056                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3057         }
3058
3059         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3060                 END_PROFILE(SMBwriteX);
3061                 return ERROR_DOS(ERRDOS,ERRbadmem);
3062         }
3063
3064         data = smb_base(inbuf) + smb_doff;
3065
3066         if(CVAL(inbuf,smb_wct) == 14) {
3067 #ifdef LARGE_SMB_OFF_T
3068                 /*
3069                  * This is a large offset (64 bit) write.
3070                  */
3071                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3072
3073 #else /* !LARGE_SMB_OFF_T */
3074
3075                 /*
3076                  * Ensure we haven't been sent a >32 bit offset.
3077                  */
3078
3079                 if(IVAL(inbuf,smb_vwv12) != 0) {
3080                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3081 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3082                         END_PROFILE(SMBwriteX);
3083                         return ERROR_DOS(ERRDOS,ERRbadaccess);
3084                 }
3085
3086 #endif /* LARGE_SMB_OFF_T */
3087         }
3088
3089         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3090                 END_PROFILE(SMBwriteX);
3091                 return ERROR_DOS(ERRDOS,ERRlock);
3092         }
3093
3094         /* X/Open SMB protocol says that, unlike SMBwrite
3095         if the length is zero then NO truncation is
3096         done, just a write of zero. To truncate a file,
3097         use SMBwrite. */
3098
3099         if(numtowrite == 0) {
3100                 nwritten = 0;
3101         } else {
3102
3103                 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3104                                         fsp,data,startpos,numtowrite)) {
3105                         END_PROFILE(SMBwriteX);
3106                         return -1;
3107                 }
3108
3109                 nwritten = write_file(fsp,data,startpos,numtowrite);
3110         }
3111   
3112         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3113                 END_PROFILE(SMBwriteX);
3114                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3115         }
3116
3117         SSVAL(outbuf,smb_vwv2,nwritten);
3118         if (large_writeX)
3119                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3120
3121         if (nwritten < (ssize_t)numtowrite) {
3122                 SCVAL(outbuf,smb_rcls,ERRHRD);
3123                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3124         }
3125
3126         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3127                 fsp->fnum, (int)numtowrite, (int)nwritten));
3128
3129         sync_file(conn, fsp, write_through);
3130
3131         END_PROFILE(SMBwriteX);
3132         return chain_reply(inbuf,outbuf,length,bufsize);
3133 }
3134
3135 /****************************************************************************
3136  Reply to a lseek.
3137 ****************************************************************************/
3138
3139 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3140 {
3141         SMB_OFF_T startpos;
3142         SMB_OFF_T res= -1;
3143         int mode,umode;
3144         int outsize = 0;
3145         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3146         START_PROFILE(SMBlseek);
3147
3148         CHECK_FSP(fsp,conn);
3149
3150         flush_write_cache(fsp, SEEK_FLUSH);
3151
3152         mode = SVAL(inbuf,smb_vwv1) & 3;
3153         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3154         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3155
3156         switch (mode) {
3157                 case 0:
3158                         umode = SEEK_SET;
3159                         res = startpos;
3160                         break;
3161                 case 1:
3162                         umode = SEEK_CUR;
3163                         res = fsp->fh->pos + startpos;
3164                         break;
3165                 case 2:
3166                         umode = SEEK_END;
3167                         break;
3168                 default:
3169                         umode = SEEK_SET;
3170                         res = startpos;
3171                         break;
3172         }
3173
3174         if (umode == SEEK_END) {
3175                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3176                         if(errno == EINVAL) {
3177                                 SMB_OFF_T current_pos = startpos;
3178                                 SMB_STRUCT_STAT sbuf;
3179
3180                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3181                                         END_PROFILE(SMBlseek);
3182                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3183                                 }
3184
3185                                 current_pos += sbuf.st_size;
3186                                 if(current_pos < 0)
3187                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3188                         }
3189                 }
3190
3191                 if(res == -1) {
3192                         END_PROFILE(SMBlseek);
3193                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3194                 }
3195         }
3196
3197         fsp->fh->pos = res;
3198   
3199         outsize = set_message(outbuf,2,0,True);
3200         SIVAL(outbuf,smb_vwv0,res);
3201   
3202         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3203                 fsp->fnum, (double)startpos, (double)res, mode));
3204
3205         END_PROFILE(SMBlseek);
3206         return(outsize);
3207 }
3208
3209 /****************************************************************************
3210  Reply to a flush.
3211 ****************************************************************************/
3212
3213 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3214 {
3215         int outsize = set_message(outbuf,0,0,False);
3216         uint16 fnum = SVAL(inbuf,smb_vwv0);
3217         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3218         START_PROFILE(SMBflush);
3219
3220         if (fnum != 0xFFFF)
3221                 CHECK_FSP(fsp,conn);
3222         
3223         if (!fsp) {
3224                 file_sync_all(conn);
3225         } else {
3226                 sync_file(conn,fsp, True);
3227         }
3228         
3229         DEBUG(3,("flush\n"));
3230         END_PROFILE(SMBflush);
3231         return(outsize);
3232 }
3233
3234 /****************************************************************************
3235  Reply to a exit.
3236  conn POINTER CAN BE NULL HERE !
3237 ****************************************************************************/
3238
3239 int reply_exit(connection_struct *conn, 
3240                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3241 {
3242         int outsize;
3243         START_PROFILE(SMBexit);
3244
3245         file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3246
3247         outsize = set_message(outbuf,0,0,False);
3248
3249         DEBUG(3,("exit\n"));
3250
3251         END_PROFILE(SMBexit);
3252         return(outsize);
3253 }
3254
3255 /****************************************************************************
3256  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3257 ****************************************************************************/
3258
3259 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3260                 int dum_buffsize)
3261 {
3262         int outsize = 0;
3263         time_t mtime;
3264         int32 eclass = 0, err = 0;
3265         files_struct *fsp = NULL;
3266         START_PROFILE(SMBclose);
3267
3268         outsize = set_message(outbuf,0,0,False);
3269
3270         /* If it's an IPC, pass off to the pipe handler. */
3271         if (IS_IPC(conn)) {
3272                 END_PROFILE(SMBclose);
3273                 return reply_pipe_close(conn, inbuf,outbuf);
3274         }
3275
3276         fsp = file_fsp(inbuf,smb_vwv0);
3277
3278         /*
3279          * We can only use CHECK_FSP if we know it's not a directory.
3280          */
3281
3282         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3283                 END_PROFILE(SMBclose);
3284                 return ERROR_DOS(ERRDOS,ERRbadfid);
3285         }
3286
3287         if(fsp->is_directory) {
3288                 /*
3289                  * Special case - close NT SMB directory handle.
3290                  */
3291                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3292                 close_file(fsp,NORMAL_CLOSE);
3293         } else {
3294                 /*
3295                  * Close ordinary file.
3296                  */
3297                 int close_err;
3298                 pstring file_name;
3299
3300                 /* Save the name for time set in close. */
3301                 pstrcpy( file_name, fsp->fsp_name);
3302
3303                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3304                          fsp->fh->fd, fsp->fnum,
3305                          conn->num_files_open));
3306  
3307                 /*
3308                  * Take care of any time sent in the close.
3309                  */
3310
3311                 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3312                 fsp_set_pending_modtime(fsp, mtime);
3313
3314                 /*
3315                  * close_file() returns the unix errno if an error
3316                  * was detected on close - normally this is due to
3317                  * a disk full error. If not then it was probably an I/O error.
3318                  */
3319  
3320                 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3321                         errno = close_err;
3322                         END_PROFILE(SMBclose);
3323                         return (UNIXERROR(ERRHRD,ERRgeneral));
3324                 }
3325         }  
3326
3327         /* We have a cached error */
3328         if(eclass || err) {
3329                 END_PROFILE(SMBclose);
3330                 return ERROR_DOS(eclass,err);
3331         }
3332
3333         END_PROFILE(SMBclose);
3334         return(outsize);
3335 }
3336
3337 /****************************************************************************
3338  Reply to a writeclose (Core+ protocol).
3339 ****************************************************************************/
3340
3341 int reply_writeclose(connection_struct *conn,
3342                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3343 {
3344         size_t numtowrite;
3345         ssize_t nwritten = -1;
3346         int outsize = 0;
3347         int close_err = 0;
3348         SMB_OFF_T startpos;
3349         char *data;
3350         time_t mtime;
3351         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3352         START_PROFILE(SMBwriteclose);
3353
3354         CHECK_FSP(fsp,conn);
3355         if (!CHECK_WRITE(fsp)) {
3356                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3357         }
3358
3359         numtowrite = SVAL(inbuf,smb_vwv1);
3360         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3361         mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3362         data = smb_buf(inbuf) + 1;
3363   
3364         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3365                 END_PROFILE(SMBwriteclose);
3366                 return ERROR_DOS(ERRDOS,ERRlock);
3367         }
3368   
3369         nwritten = write_file(fsp,data,startpos,numtowrite);
3370
3371         set_filetime(conn, fsp->fsp_name,mtime);
3372   
3373         /*
3374          * More insanity. W2K only closes the file if writelen > 0.
3375          * JRA.
3376          */
3377
3378         if (numtowrite) {
3379                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3380                         fsp->fsp_name ));
3381                 close_err = close_file(fsp,NORMAL_CLOSE);
3382         }
3383
3384         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3385                  fsp->fnum, (int)numtowrite, (int)nwritten,
3386                  conn->num_files_open));
3387   
3388         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3389                 END_PROFILE(SMBwriteclose);
3390                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3391         }
3392  
3393         if(close_err != 0) {
3394                 errno = close_err;
3395                 END_PROFILE(SMBwriteclose);
3396                 return(UNIXERROR(ERRHRD,ERRgeneral));
3397         }
3398  
3399         outsize = set_message(outbuf,1,0,True);
3400   
3401         SSVAL(outbuf,smb_vwv0,nwritten);
3402         END_PROFILE(SMBwriteclose);
3403         return(outsize);
3404 }
3405
3406 #undef DBGC_CLASS
3407 #define DBGC_CLASS DBGC_LOCKING
3408
3409 /****************************************************************************
3410  Reply to a lock.
3411 ****************************************************************************/
3412
3413 int reply_lock(connection_struct *conn,
3414                char *inbuf,char *outbuf, int length, int dum_buffsize)
3415 {
3416         int outsize = set_message(outbuf,0,0,False);
3417         SMB_BIG_UINT count,offset;
3418         NTSTATUS status;
3419         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3420
3421         START_PROFILE(SMBlock);
3422
3423         CHECK_FSP(fsp,conn);
3424
3425         release_level_2_oplocks_on_change(fsp);
3426
3427         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3428         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3429
3430         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3431                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3432
3433         status = do_lock(fsp,
3434                         (uint32)SVAL(inbuf,smb_pid),
3435                         count,
3436                         offset,
3437                         WRITE_LOCK,
3438                         WINDOWS_LOCK,
3439                         0 /* zero timeout. */);
3440
3441         if (NT_STATUS_V(status)) {
3442 #if 0
3443                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3444                 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3445                         /*
3446                          * A blocking lock was requested. Package up
3447                          * this smb into a queued request and push it
3448                          * onto the blocking lock queue.
3449                          */
3450                         if(push_blocking_lock_request(inbuf, length,
3451                                 fsp,
3452                                 -1,
3453                                 0,
3454                                 SVAL(inbuf,smb_pid),
3455                                 WRITE_LOCK,
3456                                 WINDOWS_LOCK,
3457                                 offset, count)) {
3458                                 END_PROFILE(SMBlock);
3459                                 return -1;
3460                         }
3461                 }
3462 #endif
3463                 END_PROFILE(SMBlock);
3464                 return ERROR_NT(status);
3465         }
3466
3467         END_PROFILE(SMBlock);
3468         return(outsize);
3469 }
3470
3471 /****************************************************************************
3472  Reply to a unlock.
3473 ****************************************************************************/
3474
3475 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3476                  int dum_buffsize)
3477 {
3478         int outsize = set_message(outbuf,0,0,False);
3479         SMB_BIG_UINT count,offset;
3480         NTSTATUS status;
3481         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3482         START_PROFILE(SMBunlock);
3483
3484         CHECK_FSP(fsp,conn);
3485         
3486         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3487         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3488         
3489         status = do_unlock(fsp,
3490                         (uint32)SVAL(inbuf,smb_pid),
3491                         count,
3492                         offset,
3493                         WINDOWS_LOCK);
3494
3495         if (NT_STATUS_V(status)) {
3496                 END_PROFILE(SMBunlock);
3497                 return ERROR_NT(status);
3498         }
3499
3500         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3501                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3502         
3503         END_PROFILE(SMBunlock);
3504         return(outsize);
3505 }
3506
3507 #undef DBGC_CLASS
3508 #define DBGC_CLASS DBGC_ALL
3509
3510 /****************************************************************************
3511  Reply to a tdis.
3512  conn POINTER CAN BE NULL HERE !
3513 ****************************************************************************/
3514
3515 int reply_tdis(connection_struct *conn, 
3516                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3517 {
3518         int outsize = set_message(outbuf,0,0,False);
3519         uint16 vuid;
3520         START_PROFILE(SMBtdis);
3521
3522         vuid = SVAL(inbuf,smb_uid);
3523
3524         if (!conn) {
3525                 DEBUG(4,("Invalid connection in tdis\n"));
3526                 END_PROFILE(SMBtdis);
3527                 return ERROR_DOS(ERRSRV,ERRinvnid);
3528         }
3529
3530         conn->used = False;
3531
3532         close_cnum(conn,vuid);
3533   
3534         END_PROFILE(SMBtdis);
3535         return outsize;
3536 }
3537
3538 /****************************************************************************
3539  Reply to a echo.
3540  conn POINTER CAN BE NULL HERE !
3541 ****************************************************************************/
3542
3543 int reply_echo(connection_struct *conn,
3544                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3545 {
3546         int smb_reverb = SVAL(inbuf,smb_vwv0);
3547         int seq_num;
3548         unsigned int data_len = smb_buflen(inbuf);
3549         int outsize = set_message(outbuf,1,data_len,True);
3550         START_PROFILE(SMBecho);
3551
3552         if (data_len > BUFFER_SIZE) {
3553                 DEBUG(0,("reply_echo: data_len too large.\n"));
3554                 END_PROFILE(SMBecho);
3555                 return -1;
3556         }
3557
3558         /* copy any incoming data back out */
3559         if (data_len > 0)
3560                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3561
3562         if (smb_reverb > 100) {
3563                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3564                 smb_reverb = 100;
3565         }
3566
3567         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3568                 SSVAL(outbuf,smb_vwv0,seq_num);
3569
3570                 smb_setlen(outbuf,outsize - 4);
3571
3572                 show_msg(outbuf);
3573                 if (!send_smb(smbd_server_fd(),outbuf))
3574                         exit_server("reply_echo: send_smb failed.");
3575         }
3576
3577         DEBUG(3,("echo %d times\n", smb_reverb));
3578
3579         smb_echo_count++;
3580
3581         END_PROFILE(SMBecho);
3582         return -1;
3583 }
3584
3585 /****************************************************************************
3586  Reply to a printopen.
3587 ****************************************************************************/
3588
3589 int reply_printopen(connection_struct *conn, 
3590                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3591 {
3592         int outsize = 0;
3593         files_struct *fsp;
3594         NTSTATUS status;
3595         
3596         START_PROFILE(SMBsplopen);
3597         
3598         if (!CAN_PRINT(conn)) {
3599                 END_PROFILE(SMBsplopen);
3600                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3601         }
3602
3603         /* Open for exclusive use, write only. */
3604         status = print_fsp_open(conn, NULL, &fsp);
3605
3606         if (!NT_STATUS_IS_OK(status)) {
3607                 END_PROFILE(SMBsplopen);
3608                 return(ERROR_NT(status));
3609         }
3610
3611         outsize = set_message(outbuf,1,0,True);
3612         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3613   
3614         DEBUG(3,("openprint fd=%d fnum=%d\n",
3615                  fsp->fh->fd, fsp->fnum));
3616
3617         END_PROFILE(SMBsplopen);
3618         return(outsize);
3619 }
3620
3621 /****************************************************************************
3622  Reply to a printclose.
3623 ****************************************************************************/
3624
3625 int reply_printclose(connection_struct *conn,
3626                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3627 {
3628         int outsize = set_message(outbuf,0,0,False);
3629         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3630         int close_err = 0;
3631         START_PROFILE(SMBsplclose);
3632
3633         CHECK_FSP(fsp,conn);
3634
3635         if (!CAN_PRINT(conn)) {
3636                 END_PROFILE(SMBsplclose);
3637                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3638         }
3639   
3640         DEBUG(3,("printclose fd=%d fnum=%d\n",
3641                  fsp->fh->fd,fsp->fnum));
3642   
3643         close_err = close_file(fsp,NORMAL_CLOSE);
3644
3645         if(close_err != 0) {
3646                 errno = close_err;
3647                 END_PROFILE(SMBsplclose);
3648                 return(UNIXERROR(ERRHRD,ERRgeneral));
3649         }
3650
3651         END_PROFILE(SMBsplclose);
3652         return(outsize);
3653 }
3654
3655 /****************************************************************************
3656  Reply to a printqueue.
3657 ****************************************************************************/
3658
3659 int reply_printqueue(connection_struct *conn,
3660                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3661 {
3662         int outsize = set_message(outbuf,2,3,True);
3663         int max_count = SVAL(inbuf,smb_vwv0);
3664         int start_index = SVAL(inbuf,smb_vwv1);
3665         START_PROFILE(SMBsplretq);
3666
3667         /* we used to allow the client to get the cnum wrong, but that
3668            is really quite gross and only worked when there was only
3669            one printer - I think we should now only accept it if they
3670            get it right (tridge) */
3671         if (!CAN_PRINT(conn)) {
3672                 END_PROFILE(SMBsplretq);
3673                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3674         }
3675
3676         SSVAL(outbuf,smb_vwv0,0);
3677         SSVAL(outbuf,smb_vwv1,0);
3678         SCVAL(smb_buf(outbuf),0,1);
3679         SSVAL(smb_buf(outbuf),1,0);
3680   
3681         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3682                  start_index, max_count));
3683
3684         {
3685                 print_queue_struct *queue = NULL;
3686                 print_status_struct status;
3687                 char *p = smb_buf(outbuf) + 3;
3688                 int count = print_queue_status(SNUM(conn), &queue, &status);
3689                 int num_to_get = ABS(max_count);
3690                 int first = (max_count>0?start_index:start_index+max_count+1);
3691                 int i;
3692
3693                 if (first >= count)
3694                         num_to_get = 0;
3695                 else
3696                         num_to_get = MIN(num_to_get,count-first);
3697     
3698
3699                 for (i=first;i<first+num_to_get;i++) {
3700                         srv_put_dos_date2(p,0,queue[i].time);
3701                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3702                         SSVAL(p,5, queue[i].job);
3703                         SIVAL(p,7,queue[i].size);
3704                         SCVAL(p,11,0);
3705                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3706                         p += 28;
3707                 }
3708
3709                 if (count > 0) {
3710                         outsize = set_message(outbuf,2,28*count+3,False); 
3711                         SSVAL(outbuf,smb_vwv0,count);
3712                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3713                         SCVAL(smb_buf(outbuf),0,1);
3714                         SSVAL(smb_buf(outbuf),1,28*count);
3715                 }
3716
3717                 SAFE_FREE(queue);
3718           
3719                 DEBUG(3,("%d entries returned in queue\n",count));
3720         }
3721   
3722         END_PROFILE(SMBsplretq);
3723         return(outsize);
3724 }
3725
3726 /****************************************************************************
3727  Reply to a printwrite.
3728 ****************************************************************************/
3729
3730 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3731 {
3732         int numtowrite;
3733         int outsize = set_message(outbuf,0,0,False);
3734         char *data;
3735         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3736
3737         START_PROFILE(SMBsplwr);
3738   
3739         if (!CAN_PRINT(conn)) {
3740                 END_PROFILE(SMBsplwr);
3741                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3742         }
3743
3744         CHECK_FSP(fsp,conn);
3745         if (!CHECK_WRITE(fsp)) {
3746                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3747         }
3748
3749         numtowrite = SVAL(smb_buf(inbuf),1);
3750         data = smb_buf(inbuf) + 3;
3751   
3752         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3753                 END_PROFILE(SMBsplwr);
3754                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3755         }
3756
3757         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3758   
3759         END_PROFILE(SMBsplwr);
3760         return(outsize);
3761 }
3762
3763 /****************************************************************************
3764  The guts of the mkdir command, split out so it may be called by the NT SMB
3765  code. 
3766 ****************************************************************************/
3767
3768 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3769 {
3770         int ret= -1;
3771         
3772         if(!CAN_WRITE(conn)) {
3773                 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3774                 errno = EACCES;
3775                 return map_nt_error_from_unix(errno);
3776         }
3777
3778         if (bad_path) {
3779                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3780         }
3781
3782         if (!check_name(directory, conn)) {
3783                 if(errno == ENOENT) {
3784                         if (bad_path) {
3785                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3786                         } else {
3787                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3788                         }
3789                 }
3790                 return map_nt_error_from_unix(errno);
3791         }
3792
3793         ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3794         if (ret == -1) {
3795                 if(errno == ENOENT) {
3796                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3797                 }
3798                 return map_nt_error_from_unix(errno);
3799         }
3800         
3801         return NT_STATUS_OK;
3802 }
3803
3804 /****************************************************************************
3805  Reply to a mkdir.
3806 ****************************************************************************/
3807
3808 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3809 {
3810         pstring directory;
3811         int outsize;
3812         NTSTATUS status;
3813         BOOL bad_path = False;
3814         SMB_STRUCT_STAT sbuf;
3815
3816         START_PROFILE(SMBmkdir);
3817  
3818         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3819         if (!NT_STATUS_IS_OK(status)) {
3820                 END_PROFILE(SMBmkdir);
3821                 return ERROR_NT(status);
3822         }
3823
3824         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3825
3826         unix_convert(directory,conn,0,&bad_path,&sbuf);
3827
3828         if( is_ntfs_stream_name(directory)) {
3829                 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3830                 END_PROFILE(SMBmkdir);
3831                 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
3832         }
3833
3834         status = mkdir_internal(conn, directory,bad_path);
3835         if (!NT_STATUS_IS_OK(status)) {
3836
3837                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) &&
3838                     !use_nt_status()) {
3839                         /*
3840                          * Yes, in the DOS error code case we get a
3841                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3842                          * samba4 torture test.
3843                          */
3844                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3845                 }
3846
3847                 END_PROFILE(SMBmkdir);
3848                 return ERROR_NT(status);
3849         }
3850
3851         if (lp_inherit_owner(SNUM(conn))) {
3852                 /* Ensure we're checking for a symlink here.... */
3853                 /* We don't want to get caught by a symlink racer. */
3854
3855                 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3856                         END_PROFILE(SMBmkdir);
3857                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3858                 }
3859                                                                                                                                                    
3860                 if(!S_ISDIR(sbuf.st_mode)) {
3861                         DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3862                         END_PROFILE(SMBmkdir);
3863                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3864                 }
3865
3866                 change_owner_to_parent(conn, NULL, directory, &sbuf);
3867         }
3868
3869         outsize = set_message(outbuf,0,0,False);
3870
3871         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3872
3873         END_PROFILE(SMBmkdir);
3874         return(outsize);
3875 }
3876
3877 /****************************************************************************
3878  Static function used by reply_rmdir to delete an entire directory
3879  tree recursively. Return False on ok, True on fail.
3880 ****************************************************************************/
3881
3882 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3883 {
3884         const char *dname = NULL;
3885         BOOL ret = False;
3886         long offset = 0;
3887         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3888
3889         if(dir_hnd == NULL)
3890                 return True;
3891
3892         while((dname = ReadDirName(dir_hnd, &offset))) {
3893                 pstring fullname;
3894                 SMB_STRUCT_STAT st;
3895
3896                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3897                         continue;
3898
3899                 if (!is_visible_file(conn, directory, dname, &st, False))
3900                         continue;
3901
3902                 /* Construct the full name. */
3903                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3904                         errno = ENOMEM;
3905                         ret = True;
3906                         break;
3907                 }
3908
3909                 pstrcpy(fullname, directory);
3910                 pstrcat(fullname, "/");
3911                 pstrcat(fullname, dname);
3912
3913                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3914                         ret = True;
3915                         break;
3916                 }
3917
3918                 if(st.st_mode & S_IFDIR) {
3919                         if(recursive_rmdir(conn, fullname)!=0) {
3920                                 ret = True;
3921                                 break;
3922                         }
3923                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3924                                 ret = True;
3925                                 break;
3926                         }
3927                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3928                         ret = True;
3929                         break;
3930                 }
3931         }
3932         CloseDir(dir_hnd);
3933         return ret;
3934 }
3935
3936 /****************************************************************************
3937  The internals of the rmdir code - called elsewhere.
3938 ****************************************************************************/
3939
3940 BOOL rmdir_internals(connection_struct *conn, char *directory)
3941 {
3942         BOOL ok;
3943         SMB_STRUCT_STAT st;
3944