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