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