s3: smbd: Add srvstr_get_path_wcard_posix().
[samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47
48 /****************************************************************************
49  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50  path or anything including wildcards.
51  We're assuming here that '/' is not the second byte in any multibyte char
52  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53  set.
54 ****************************************************************************/
55
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58
59 static NTSTATUS check_path_syntax_internal(char *path,
60                                            bool posix_path,
61                                            bool *p_last_component_contains_wcard)
62 {
63         char *d = path;
64         const char *s = path;
65         NTSTATUS ret = NT_STATUS_OK;
66         bool start_of_name_component = True;
67         bool stream_started = false;
68
69         *p_last_component_contains_wcard = False;
70
71         while (*s) {
72                 if (stream_started) {
73                         switch (*s) {
74                         case '/':
75                         case '\\':
76                                 return NT_STATUS_OBJECT_NAME_INVALID;
77                         case ':':
78                                 if (s[1] == '\0') {
79                                         return NT_STATUS_OBJECT_NAME_INVALID;
80                                 }
81                                 if (strchr_m(&s[1], ':')) {
82                                         return NT_STATUS_OBJECT_NAME_INVALID;
83                                 }
84                                 break;
85                         }
86                 }
87
88                 if ((*s == ':') && !posix_path && !stream_started) {
89                         if (*p_last_component_contains_wcard) {
90                                 return NT_STATUS_OBJECT_NAME_INVALID;
91                         }
92                         /* Stream names allow more characters than file names.
93                            We're overloading posix_path here to allow a wider
94                            range of characters. If stream_started is true this
95                            is still a Windows path even if posix_path is true.
96                            JRA.
97                         */
98                         stream_started = true;
99                         start_of_name_component = false;
100                         posix_path = true;
101
102                         if (s[1] == '\0') {
103                                 return NT_STATUS_OBJECT_NAME_INVALID;
104                         }
105                 }
106
107                 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108                         /*
109                          * Safe to assume is not the second part of a mb char
110                          * as this is handled below.
111                          */
112                         /* Eat multiple '/' or '\\' */
113                         while (IS_PATH_SEP(*s,posix_path)) {
114                                 s++;
115                         }
116                         if ((d != path) && (*s != '\0')) {
117                                 /* We only care about non-leading or trailing '/' or '\\' */
118                                 *d++ = '/';
119                         }
120
121                         start_of_name_component = True;
122                         /* New component. */
123                         *p_last_component_contains_wcard = False;
124                         continue;
125                 }
126
127                 if (start_of_name_component) {
128                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
130
131                                 /*
132                                  * No mb char starts with '.' so we're safe checking the directory separator here.
133                                  */
134
135                                 /* If  we just added a '/' - delete it */
136                                 if ((d > path) && (*(d-1) == '/')) {
137                                         *(d-1) = '\0';
138                                         d--;
139                                 }
140
141                                 /* Are we at the start ? Can't go back further if so. */
142                                 if (d <= path) {
143                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
144                                         break;
145                                 }
146                                 /* Go back one level... */
147                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
148                                 /* NOTE - if this assumption is invalid we are not in good shape... */
149                                 /* Decrement d first as d points to the *next* char to write into. */
150                                 for (d--; d > path; d--) {
151                                         if (*d == '/')
152                                                 break;
153                                 }
154                                 s += 2; /* Else go past the .. */
155                                 /* We're still at the start of a name component, just the previous one. */
156                                 continue;
157
158                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
159                                 if (posix_path) {
160                                         /* Eat the '.' */
161                                         s++;
162                                         continue;
163                                 }
164                         }
165
166                 }
167
168                 if (!(*s & 0x80)) {
169                         if (!posix_path) {
170                                 if (*s <= 0x1f || *s == '|') {
171                                         return NT_STATUS_OBJECT_NAME_INVALID;
172                                 }
173                                 switch (*s) {
174                                         case '*':
175                                         case '?':
176                                         case '<':
177                                         case '>':
178                                         case '"':
179                                                 *p_last_component_contains_wcard = True;
180                                                 break;
181                                         default:
182                                                 break;
183                                 }
184                         }
185                         *d++ = *s++;
186                 } else {
187                         size_t siz;
188                         /* Get the size of the next MB character. */
189                         next_codepoint(s,&siz);
190                         switch(siz) {
191                                 case 5:
192                                         *d++ = *s++;
193                                         /*fall through*/
194                                 case 4:
195                                         *d++ = *s++;
196                                         /*fall through*/
197                                 case 3:
198                                         *d++ = *s++;
199                                         /*fall through*/
200                                 case 2:
201                                         *d++ = *s++;
202                                         /*fall through*/
203                                 case 1:
204                                         *d++ = *s++;
205                                         break;
206                                 default:
207                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208                                         *d = '\0';
209                                         return NT_STATUS_INVALID_PARAMETER;
210                         }
211                 }
212                 start_of_name_component = False;
213         }
214
215         *d = '\0';
216
217         return ret;
218 }
219
220 /****************************************************************************
221  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222  No wildcards allowed.
223 ****************************************************************************/
224
225 NTSTATUS check_path_syntax(char *path)
226 {
227         bool ignore;
228         return check_path_syntax_internal(path, False, &ignore);
229 }
230
231 /****************************************************************************
232  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233  Wildcards allowed - p_contains_wcard returns true if the last component contained
234  a wildcard.
235 ****************************************************************************/
236
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 {
239         return check_path_syntax_internal(path, False, p_contains_wcard);
240 }
241
242 /****************************************************************************
243  Check the path for a POSIX client.
244  We're assuming here that '/' is not the second byte in any multibyte char
245  set (a safe assumption).
246 ****************************************************************************/
247
248 NTSTATUS check_path_syntax_posix(char *path)
249 {
250         bool ignore;
251         return check_path_syntax_internal(path, True, &ignore);
252 }
253
254 /****************************************************************************
255  Pull a string and check the path allowing a wilcard - provide for error return.
256  Passes in posix flag.
257 ****************************************************************************/
258
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260                         const char *base_ptr,
261                         uint16_t smb_flags2,
262                         char **pp_dest,
263                         const char *src,
264                         size_t src_len,
265                         int flags,
266                         bool posix_pathnames,
267                         NTSTATUS *err,
268                         bool *contains_wcard)
269 {
270         size_t ret;
271
272         *pp_dest = NULL;
273
274         ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275                                  src_len, flags);
276
277         if (!*pp_dest) {
278                 *err = NT_STATUS_INVALID_PARAMETER;
279                 return ret;
280         }
281
282         *contains_wcard = False;
283
284         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
285                 /*
286                  * For a DFS path the function parse_dfs_path()
287                  * will do the path processing, just make a copy.
288                  */
289                 *err = NT_STATUS_OK;
290                 return ret;
291         }
292
293         if (posix_pathnames) {
294                 *err = check_path_syntax_posix(*pp_dest);
295         } else {
296                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
297         }
298
299         return ret;
300 }
301
302 /****************************************************************************
303  Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
305
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307                         const char *base_ptr,
308                         uint16_t smb_flags2,
309                         char **pp_dest,
310                         const char *src,
311                         size_t src_len,
312                         int flags,
313                         NTSTATUS *err,
314                         bool *contains_wcard)
315 {
316         return srvstr_get_path_wcard_internal(ctx,
317                         base_ptr,
318                         smb_flags2,
319                         pp_dest,
320                         src,
321                         src_len,
322                         flags,
323                         lp_posix_pathnames(),
324                         err,
325                         contains_wcard);
326 }
327
328 /****************************************************************************
329  Pull a string and check the path allowing a wilcard - provide for error return.
330  posix_pathnames version.
331 ****************************************************************************/
332
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334                         const char *base_ptr,
335                         uint16_t smb_flags2,
336                         char **pp_dest,
337                         const char *src,
338                         size_t src_len,
339                         int flags,
340                         NTSTATUS *err,
341                         bool *contains_wcard)
342 {
343         return srvstr_get_path_wcard_internal(ctx,
344                         base_ptr,
345                         smb_flags2,
346                         pp_dest,
347                         src,
348                         src_len,
349                         flags,
350                         true,
351                         err,
352                         contains_wcard);
353 }
354
355 /****************************************************************************
356  Pull a string and check the path - provide for error return.
357 ****************************************************************************/
358
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360                         const char *base_ptr,
361                         uint16_t smb_flags2,
362                         char **pp_dest,
363                         const char *src,
364                         size_t src_len,
365                         int flags,
366                         NTSTATUS *err)
367 {
368         bool ignore;
369         if (lp_posix_pathnames()) {
370                 return srvstr_get_path_wcard_internal(ctx,
371                                 base_ptr,
372                                 smb_flags2,
373                                 pp_dest,
374                                 src,
375                                 src_len,
376                                 flags,
377                                 true,
378                                 err,
379                                 &ignore);
380         } else {
381                 return srvstr_get_path_wcard_internal(ctx,
382                                 base_ptr,
383                                 smb_flags2,
384                                 pp_dest,
385                                 src,
386                                 src_len,
387                                 flags,
388                                 false,
389                                 err,
390                                 &ignore);
391         }
392 }
393
394 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
395                                  char **pp_dest, const char *src, int flags,
396                                  NTSTATUS *err, bool *contains_wcard)
397 {
398         ssize_t bufrem = smbreq_bufrem(req, src);
399
400         if (bufrem < 0) {
401                 *err = NT_STATUS_INVALID_PARAMETER;
402                 return 0;
403         }
404
405         if (lp_posix_pathnames()) {
406                 return srvstr_get_path_wcard_internal(mem_ctx,
407                                 (const char *)req->inbuf,
408                                 req->flags2,
409                                 pp_dest,
410                                 src,
411                                 bufrem,
412                                 flags,
413                                 true,
414                                 err,
415                                 contains_wcard);
416         } else {
417                 return srvstr_get_path_wcard_internal(mem_ctx,
418                                 (const char *)req->inbuf,
419                                 req->flags2,
420                                 pp_dest,
421                                 src,
422                                 bufrem,
423                                 flags,
424                                 false,
425                                 err,
426                                 contains_wcard);
427         }
428 }
429
430 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
431                            char **pp_dest, const char *src, int flags,
432                            NTSTATUS *err)
433 {
434         bool ignore;
435         return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
436                                          flags, err, &ignore);
437 }
438
439 /**
440  * pull a string from the smb_buf part of a packet. In this case the
441  * string can either be null terminated or it can be terminated by the
442  * end of the smbbuf area
443  */
444 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
445                               char **dest, const uint8_t *src, int flags)
446 {
447         ssize_t bufrem = smbreq_bufrem(req, src);
448
449         if (bufrem < 0) {
450                 return 0;
451         }
452
453         return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
454                                   bufrem, flags);
455 }
456
457 /****************************************************************************
458  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
459 ****************************************************************************/
460
461 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
462                     files_struct *fsp)
463 {
464         if ((fsp == NULL) || (conn == NULL)) {
465                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
466                 return False;
467         }
468         if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
469                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
470                 return False;
471         }
472         return True;
473 }
474
475 /****************************************************************************
476  Check if we have a correct fsp pointing to a file.
477 ****************************************************************************/
478
479 bool check_fsp(connection_struct *conn, struct smb_request *req,
480                files_struct *fsp)
481 {
482         if (!check_fsp_open(conn, req, fsp)) {
483                 return False;
484         }
485         if (fsp->is_directory) {
486                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
487                 return False;
488         }
489         if (fsp->fh->fd == -1) {
490                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
491                 return False;
492         }
493         fsp->num_smb_operations++;
494         return True;
495 }
496
497 /****************************************************************************
498  Check if we have a correct fsp pointing to a quota fake file. Replacement for
499  the CHECK_NTQUOTA_HANDLE_OK macro.
500 ****************************************************************************/
501
502 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
503                               files_struct *fsp)
504 {
505         if (!check_fsp_open(conn, req, fsp)) {
506                 return false;
507         }
508
509         if (fsp->is_directory) {
510                 return false;
511         }
512
513         if (fsp->fake_file_handle == NULL) {
514                 return false;
515         }
516
517         if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
518                 return false;
519         }
520
521         if (fsp->fake_file_handle->private_data == NULL) {
522                 return false;
523         }
524
525         return true;
526 }
527
528 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
529                                      const char *name, int name_type)
530 {
531         char *trim_name;
532         char *trim_name_type;
533         const char *retarget_parm;
534         char *retarget;
535         char *p;
536         int retarget_type = 0x20;
537         int retarget_port = NBT_SMB_PORT;
538         struct sockaddr_storage retarget_addr;
539         struct sockaddr_in *in_addr;
540         bool ret = false;
541         uint8_t outbuf[10];
542
543         if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
544                 return false;
545         }
546
547         trim_name = talloc_strdup(talloc_tos(), name);
548         if (trim_name == NULL) {
549                 goto fail;
550         }
551         trim_char(trim_name, ' ', ' ');
552
553         trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
554                                          name_type);
555         if (trim_name_type == NULL) {
556                 goto fail;
557         }
558
559         retarget_parm = lp_parm_const_string(-1, "netbios retarget",
560                                              trim_name_type, NULL);
561         if (retarget_parm == NULL) {
562                 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
563                                                      trim_name, NULL);
564         }
565         if (retarget_parm == NULL) {
566                 goto fail;
567         }
568
569         retarget = talloc_strdup(trim_name, retarget_parm);
570         if (retarget == NULL) {
571                 goto fail;
572         }
573
574         DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
575
576         p = strchr(retarget, ':');
577         if (p != NULL) {
578                 *p++ = '\0';
579                 retarget_port = atoi(p);
580         }
581
582         p = strchr_m(retarget, '#');
583         if (p != NULL) {
584                 *p++ = '\0';
585                 if (sscanf(p, "%x", &retarget_type) != 1) {
586                         goto fail;
587                 }
588         }
589
590         ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
591         if (!ret) {
592                 DEBUG(10, ("could not resolve %s\n", retarget));
593                 goto fail;
594         }
595
596         if (retarget_addr.ss_family != AF_INET) {
597                 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
598                 goto fail;
599         }
600
601         in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
602
603         _smb_setlen(outbuf, 6);
604         SCVAL(outbuf, 0, 0x84);
605         *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
606         *(uint16_t *)(outbuf+8) = htons(retarget_port);
607
608         if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
609                           NULL)) {
610                 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
611                                     "failed.");
612         }
613
614         ret = true;
615  fail:
616         TALLOC_FREE(trim_name);
617         return ret;
618 }
619
620 static void reply_called_name_not_present(char *outbuf)
621 {
622         smb_setlen(outbuf, 1);
623         SCVAL(outbuf, 0, 0x83);
624         SCVAL(outbuf, 4, 0x82);
625 }
626
627 /****************************************************************************
628  Reply to a (netbios-level) special message. 
629 ****************************************************************************/
630
631 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
632 {
633         struct smbd_server_connection *sconn = xconn->client->sconn;
634         int msg_type = CVAL(inbuf,0);
635         int msg_flags = CVAL(inbuf,1);
636         /*
637          * We only really use 4 bytes of the outbuf, but for the smb_setlen
638          * calculation & friends (srv_send_smb uses that) we need the full smb
639          * header.
640          */
641         char outbuf[smb_size];
642
643         memset(outbuf, '\0', sizeof(outbuf));
644
645         smb_setlen(outbuf,0);
646
647         switch (msg_type) {
648         case NBSSrequest: /* session request */
649         {
650                 /* inbuf_size is guarenteed to be at least 4. */
651                 fstring name1,name2;
652                 int name_type1, name_type2;
653                 int name_len1, name_len2;
654
655                 *name1 = *name2 = 0;
656
657                 if (xconn->transport.nbt.got_session) {
658                         exit_server_cleanly("multiple session request not permitted");
659                 }
660
661                 SCVAL(outbuf,0,NBSSpositive);
662                 SCVAL(outbuf,3,0);
663
664                 /* inbuf_size is guaranteed to be at least 4. */
665                 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
666                 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
667                         DEBUG(0,("Invalid name length in session request\n"));
668                         reply_called_name_not_present(outbuf);
669                         break;
670                 }
671                 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
672                 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
673                         DEBUG(0,("Invalid name length in session request\n"));
674                         reply_called_name_not_present(outbuf);
675                         break;
676                 }
677
678                 name_type1 = name_extract((unsigned char *)inbuf,
679                                 inbuf_size,(unsigned int)4,name1);
680                 name_type2 = name_extract((unsigned char *)inbuf,
681                                 inbuf_size,(unsigned int)(4 + name_len1),name2);
682
683                 if (name_type1 == -1 || name_type2 == -1) {
684                         DEBUG(0,("Invalid name type in session request\n"));
685                         reply_called_name_not_present(outbuf);
686                         break;
687                 }
688
689                 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
690                          name1, name_type1, name2, name_type2));
691
692                 if (netbios_session_retarget(xconn, name1, name_type1)) {
693                         exit_server_cleanly("retargeted client");
694                 }
695
696                 /*
697                  * Windows NT/2k uses "*SMBSERVER" and XP uses
698                  * "*SMBSERV" arrggg!!!
699                  */
700                 if (strequal(name1, "*SMBSERVER     ")
701                     || strequal(name1, "*SMBSERV       "))  {
702                         char *raddr;
703
704                         raddr = tsocket_address_inet_addr_string(sconn->remote_address,
705                                                                  talloc_tos());
706                         if (raddr == NULL) {
707                                 exit_server_cleanly("could not allocate raddr");
708                         }
709
710                         fstrcpy(name1, raddr);
711                 }
712
713                 set_local_machine_name(name1, True);
714                 set_remote_machine_name(name2, True);
715
716                 if (is_ipaddress(sconn->remote_hostname)) {
717                         char *p = discard_const_p(char, sconn->remote_hostname);
718
719                         talloc_free(p);
720
721                         sconn->remote_hostname = talloc_strdup(sconn,
722                                                 get_remote_machine_name());
723                         if (sconn->remote_hostname == NULL) {
724                                 exit_server_cleanly("could not copy remote name");
725                         }
726                         xconn->remote_hostname = sconn->remote_hostname;
727                 }
728
729                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
730                          get_local_machine_name(), get_remote_machine_name(),
731                          name_type2));
732
733                 if (name_type2 == 'R') {
734                         /* We are being asked for a pathworks session --- 
735                            no thanks! */
736                         reply_called_name_not_present(outbuf);
737                         break;
738                 }
739
740                 reload_services(sconn, conn_snum_used, true);
741                 reopen_logs();
742
743                 xconn->transport.nbt.got_session = true;
744                 break;
745         }
746
747         case 0x89: /* session keepalive request 
748                       (some old clients produce this?) */
749                 SCVAL(outbuf,0,NBSSkeepalive);
750                 SCVAL(outbuf,3,0);
751                 break;
752
753         case NBSSpositive: /* positive session response */
754         case NBSSnegative: /* negative session response */
755         case NBSSretarget: /* retarget session response */
756                 DEBUG(0,("Unexpected session response\n"));
757                 break;
758
759         case NBSSkeepalive: /* session keepalive */
760         default:
761                 return;
762         }
763
764         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
765                     msg_type, msg_flags));
766
767         srv_send_smb(xconn, outbuf, false, 0, false, NULL);
768
769         if (CVAL(outbuf, 0) != 0x82) {
770                 exit_server_cleanly("invalid netbios session");
771         }
772         return;
773 }
774
775 /****************************************************************************
776  Reply to a tcon.
777  conn POINTER CAN BE NULL HERE !
778 ****************************************************************************/
779
780 void reply_tcon(struct smb_request *req)
781 {
782         connection_struct *conn = req->conn;
783         const char *service;
784         char *service_buf = NULL;
785         char *password = NULL;
786         char *dev = NULL;
787         int pwlen=0;
788         NTSTATUS nt_status;
789         const uint8_t *p;
790         const char *p2;
791         TALLOC_CTX *ctx = talloc_tos();
792         struct smbXsrv_connection *xconn = req->xconn;
793         NTTIME now = timeval_to_nttime(&req->request_time);
794
795         START_PROFILE(SMBtcon);
796
797         if (req->buflen < 4) {
798                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
799                 END_PROFILE(SMBtcon);
800                 return;
801         }
802
803         p = req->buf + 1;
804         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
805         p += 1;
806         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
807         p += pwlen+1;
808         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
809         p += 1;
810
811         if (service_buf == NULL || password == NULL || dev == NULL) {
812                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
813                 END_PROFILE(SMBtcon);
814                 return;
815         }
816         p2 = strrchr_m(service_buf,'\\');
817         if (p2) {
818                 service = p2+1;
819         } else {
820                 service = service_buf;
821         }
822
823         conn = make_connection(req, now, service, dev,
824                                req->vuid,&nt_status);
825         req->conn = conn;
826
827         if (!conn) {
828                 reply_nterror(req, nt_status);
829                 END_PROFILE(SMBtcon);
830                 return;
831         }
832
833         reply_outbuf(req, 2, 0);
834         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
835         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
836         SSVAL(req->outbuf,smb_tid,conn->cnum);
837
838         DEBUG(3,("tcon service=%s cnum=%d\n",
839                  service, conn->cnum));
840
841         END_PROFILE(SMBtcon);
842         return;
843 }
844
845 /****************************************************************************
846  Reply to a tcon and X.
847  conn POINTER CAN BE NULL HERE !
848 ****************************************************************************/
849
850 void reply_tcon_and_X(struct smb_request *req)
851 {
852         connection_struct *conn = req->conn;
853         const char *service = NULL;
854         TALLOC_CTX *ctx = talloc_tos();
855         /* what the cleint thinks the device is */
856         char *client_devicetype = NULL;
857         /* what the server tells the client the share represents */
858         const char *server_devicetype;
859         NTSTATUS nt_status;
860         int passlen;
861         char *path = NULL;
862         const uint8_t *p;
863         const char *q;
864         uint16_t tcon_flags;
865         struct smbXsrv_session *session = NULL;
866         NTTIME now = timeval_to_nttime(&req->request_time);
867         bool session_key_updated = false;
868         uint16_t optional_support = 0;
869         struct smbXsrv_connection *xconn = req->xconn;
870
871         START_PROFILE(SMBtconX);
872
873         if (req->wct < 4) {
874                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
875                 END_PROFILE(SMBtconX);
876                 return;
877         }
878
879         passlen = SVAL(req->vwv+3, 0);
880         tcon_flags = SVAL(req->vwv+2, 0);
881
882         /* we might have to close an old one */
883         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
884                 struct smbXsrv_tcon *tcon;
885                 NTSTATUS status;
886
887                 tcon = conn->tcon;
888                 req->conn = NULL;
889                 conn = NULL;
890
891                 /*
892                  * TODO: cancel all outstanding requests on the tcon
893                  */
894                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
895                 if (!NT_STATUS_IS_OK(status)) {
896                         DEBUG(0, ("reply_tcon_and_X: "
897                                   "smbXsrv_tcon_disconnect() failed: %s\n",
898                                   nt_errstr(status)));
899                         /*
900                          * If we hit this case, there is something completely
901                          * wrong, so we better disconnect the transport connection.
902                          */
903                         END_PROFILE(SMBtconX);
904                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
905                         return;
906                 }
907
908                 TALLOC_FREE(tcon);
909         }
910
911         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
912                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
913                 END_PROFILE(SMBtconX);
914                 return;
915         }
916
917         if (xconn->smb1.negprot.encrypted_passwords) {
918                 p = req->buf + passlen;
919         } else {
920                 p = req->buf + passlen + 1;
921         }
922
923         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
924
925         if (path == NULL) {
926                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
927                 END_PROFILE(SMBtconX);
928                 return;
929         }
930
931         /*
932          * the service name can be either: \\server\share
933          * or share directly like on the DELL PowerVault 705
934          */
935         if (*path=='\\') {
936                 q = strchr_m(path+2,'\\');
937                 if (!q) {
938                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
939                         END_PROFILE(SMBtconX);
940                         return;
941                 }
942                 service = q+1;
943         } else {
944                 service = path;
945         }
946
947         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
948                                 &client_devicetype, p,
949                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
950
951         if (client_devicetype == NULL) {
952                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
953                 END_PROFILE(SMBtconX);
954                 return;
955         }
956
957         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
958
959         nt_status = smb1srv_session_lookup(xconn,
960                                            req->vuid, now, &session);
961         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
962                 reply_force_doserror(req, ERRSRV, ERRbaduid);
963                 END_PROFILE(SMBtconX);
964                 return;
965         }
966         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
967                 reply_nterror(req, nt_status);
968                 END_PROFILE(SMBtconX);
969                 return;
970         }
971         if (!NT_STATUS_IS_OK(nt_status)) {
972                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
973                 END_PROFILE(SMBtconX);
974                 return;
975         }
976
977         if (session->global->auth_session_info == NULL) {
978                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
979                 END_PROFILE(SMBtconX);
980                 return;
981         }
982
983         /*
984          * If there is no application key defined yet
985          * we create one.
986          *
987          * This means we setup the application key on the
988          * first tcon that happens via the given session.
989          *
990          * Once the application key is defined, it does not
991          * change any more.
992          */
993         if (session->global->application_key.length == 0 &&
994             session->global->signing_key.length > 0)
995         {
996                 struct smbXsrv_session *x = session;
997                 struct auth_session_info *session_info =
998                         session->global->auth_session_info;
999                 uint8_t session_key[16];
1000
1001                 ZERO_STRUCT(session_key);
1002                 memcpy(session_key, x->global->signing_key.data,
1003                        MIN(x->global->signing_key.length, sizeof(session_key)));
1004
1005                 /*
1006                  * The application key is truncated/padded to 16 bytes
1007                  */
1008                 x->global->application_key = data_blob_talloc(x->global,
1009                                                              session_key,
1010                                                              sizeof(session_key));
1011                 ZERO_STRUCT(session_key);
1012                 if (x->global->application_key.data == NULL) {
1013                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1014                         END_PROFILE(SMBtconX);
1015                         return;
1016                 }
1017
1018                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1019                         smb_key_derivation(x->global->application_key.data,
1020                                            x->global->application_key.length,
1021                                            x->global->application_key.data);
1022                         optional_support |= SMB_EXTENDED_SIGNATURES;
1023                 }
1024
1025                 /*
1026                  * Place the application key into the session_info
1027                  */
1028                 data_blob_clear_free(&session_info->session_key);
1029                 session_info->session_key = data_blob_dup_talloc(session_info,
1030                                                 x->global->application_key);
1031                 if (session_info->session_key.data == NULL) {
1032                         data_blob_clear_free(&x->global->application_key);
1033                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1034                         END_PROFILE(SMBtconX);
1035                         return;
1036                 }
1037                 session_key_updated = true;
1038         }
1039
1040         conn = make_connection(req, now, service, client_devicetype,
1041                                req->vuid, &nt_status);
1042         req->conn =conn;
1043
1044         if (!conn) {
1045                 if (session_key_updated) {
1046                         struct smbXsrv_session *x = session;
1047                         struct auth_session_info *session_info =
1048                                 session->global->auth_session_info;
1049                         data_blob_clear_free(&x->global->application_key);
1050                         data_blob_clear_free(&session_info->session_key);
1051                 }
1052                 reply_nterror(req, nt_status);
1053                 END_PROFILE(SMBtconX);
1054                 return;
1055         }
1056
1057         if ( IS_IPC(conn) )
1058                 server_devicetype = "IPC";
1059         else if ( IS_PRINT(conn) )
1060                 server_devicetype = "LPT1:";
1061         else
1062                 server_devicetype = "A:";
1063
1064         if (get_Protocol() < PROTOCOL_NT1) {
1065                 reply_outbuf(req, 2, 0);
1066                 if (message_push_string(&req->outbuf, server_devicetype,
1067                                         STR_TERMINATE|STR_ASCII) == -1) {
1068                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1069                         END_PROFILE(SMBtconX);
1070                         return;
1071                 }
1072         } else {
1073                 /* NT sets the fstype of IPC$ to the null string */
1074                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1075
1076                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1077                         /* Return permissions. */
1078                         uint32_t perm1 = 0;
1079                         uint32_t perm2 = 0;
1080
1081                         reply_outbuf(req, 7, 0);
1082
1083                         if (IS_IPC(conn)) {
1084                                 perm1 = FILE_ALL_ACCESS;
1085                                 perm2 = FILE_ALL_ACCESS;
1086                         } else {
1087                                 perm1 = conn->share_access;
1088                         }
1089
1090                         SIVAL(req->outbuf, smb_vwv3, perm1);
1091                         SIVAL(req->outbuf, smb_vwv5, perm2);
1092                 } else {
1093                         reply_outbuf(req, 3, 0);
1094                 }
1095
1096                 if ((message_push_string(&req->outbuf, server_devicetype,
1097                                          STR_TERMINATE|STR_ASCII) == -1)
1098                     || (message_push_string(&req->outbuf, fstype,
1099                                             STR_TERMINATE) == -1)) {
1100                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1101                         END_PROFILE(SMBtconX);
1102                         return;
1103                 }
1104
1105                 /* what does setting this bit do? It is set by NT4 and
1106                    may affect the ability to autorun mounted cdroms */
1107                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1108                 optional_support |=
1109                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1110
1111                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1112                         DEBUG(2,("Serving %s as a Dfs root\n",
1113                                  lp_servicename(ctx, SNUM(conn)) ));
1114                         optional_support |= SMB_SHARE_IN_DFS;
1115                 }
1116
1117                 SSVAL(req->outbuf, smb_vwv2, optional_support);
1118         }
1119
1120         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1121         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1122
1123         DEBUG(3,("tconX service=%s \n",
1124                  service));
1125
1126         /* set the incoming and outgoing tid to the just created one */
1127         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1128         SSVAL(req->outbuf,smb_tid,conn->cnum);
1129
1130         END_PROFILE(SMBtconX);
1131
1132         req->tid = conn->cnum;
1133 }
1134
1135 /****************************************************************************
1136  Reply to an unknown type.
1137 ****************************************************************************/
1138
1139 void reply_unknown_new(struct smb_request *req, uint8_t type)
1140 {
1141         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1142                   smb_fn_name(type), type, type));
1143         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1144         return;
1145 }
1146
1147 /****************************************************************************
1148  Reply to an ioctl.
1149  conn POINTER CAN BE NULL HERE !
1150 ****************************************************************************/
1151
1152 void reply_ioctl(struct smb_request *req)
1153 {
1154         connection_struct *conn = req->conn;
1155         uint16_t device;
1156         uint16_t function;
1157         uint32_t ioctl_code;
1158         int replysize;
1159         char *p;
1160
1161         START_PROFILE(SMBioctl);
1162
1163         if (req->wct < 3) {
1164                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1165                 END_PROFILE(SMBioctl);
1166                 return;
1167         }
1168
1169         device     = SVAL(req->vwv+1, 0);
1170         function   = SVAL(req->vwv+2, 0);
1171         ioctl_code = (device << 16) + function;
1172
1173         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1174
1175         switch (ioctl_code) {
1176             case IOCTL_QUERY_JOB_INFO:
1177                     replysize = 32;
1178                     break;
1179             default:
1180                     reply_force_doserror(req, ERRSRV, ERRnosupport);
1181                     END_PROFILE(SMBioctl);
1182                     return;
1183         }
1184
1185         reply_outbuf(req, 8, replysize+1);
1186         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1187         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1188         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
1189         p = smb_buf(req->outbuf);
1190         memset(p, '\0', replysize+1); /* valgrind-safe. */
1191         p += 1;          /* Allow for alignment */
1192
1193         switch (ioctl_code) {
1194                 case IOCTL_QUERY_JOB_INFO:                  
1195                 {
1196                         NTSTATUS status;
1197                         size_t len = 0;
1198                         files_struct *fsp = file_fsp(
1199                                 req, SVAL(req->vwv+0, 0));
1200                         if (!fsp) {
1201                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1202                                 END_PROFILE(SMBioctl);
1203                                 return;
1204                         }
1205                         /* Job number */
1206                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1207
1208                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1209                                     lp_netbios_name(), 15,
1210                                     STR_TERMINATE|STR_ASCII, &len);
1211                         if (!NT_STATUS_IS_OK(status)) {
1212                                 reply_nterror(req, status);
1213                                 END_PROFILE(SMBioctl);
1214                                 return;
1215                         }
1216                         if (conn) {
1217                                 status = srvstr_push((char *)req->outbuf, req->flags2,
1218                                             p+18,
1219                                             lp_servicename(talloc_tos(),
1220                                                            SNUM(conn)),
1221                                             13, STR_TERMINATE|STR_ASCII, &len);
1222                                 if (!NT_STATUS_IS_OK(status)) {
1223                                         reply_nterror(req, status);
1224                                         END_PROFILE(SMBioctl);
1225                                         return;
1226                                 }
1227                         } else {
1228                                 memset(p+18, 0, 13);
1229                         }
1230                         break;
1231                 }
1232         }
1233
1234         END_PROFILE(SMBioctl);
1235         return;
1236 }
1237
1238 /****************************************************************************
1239  Strange checkpath NTSTATUS mapping.
1240 ****************************************************************************/
1241
1242 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1243 {
1244         /* Strange DOS error code semantics only for checkpath... */
1245         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1246                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1247                         /* We need to map to ERRbadpath */
1248                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1249                 }
1250         }
1251         return status;
1252 }
1253
1254 /****************************************************************************
1255  Reply to a checkpath.
1256 ****************************************************************************/
1257
1258 void reply_checkpath(struct smb_request *req)
1259 {
1260         connection_struct *conn = req->conn;
1261         struct smb_filename *smb_fname = NULL;
1262         char *name = NULL;
1263         NTSTATUS status;
1264         uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1265         TALLOC_CTX *ctx = talloc_tos();
1266
1267         START_PROFILE(SMBcheckpath);
1268
1269         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1270                             STR_TERMINATE, &status);
1271
1272         if (!NT_STATUS_IS_OK(status)) {
1273                 status = map_checkpath_error(req->flags2, status);
1274                 reply_nterror(req, status);
1275                 END_PROFILE(SMBcheckpath);
1276                 return;
1277         }
1278
1279         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1280
1281         status = filename_convert(ctx,
1282                                 conn,
1283                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1284                                 name,
1285                                 ucf_flags,
1286                                 NULL,
1287                                 &smb_fname);
1288
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1291                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1292                                         ERRSRV, ERRbadpath);
1293                         END_PROFILE(SMBcheckpath);
1294                         return;
1295                 }
1296                 goto path_err;
1297         }
1298
1299         if (!VALID_STAT(smb_fname->st) &&
1300             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1301                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1302                         smb_fname_str_dbg(smb_fname), strerror(errno)));
1303                 status = map_nt_error_from_unix(errno);
1304                 goto path_err;
1305         }
1306
1307         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1308                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1309                                 ERRDOS, ERRbadpath);
1310                 goto out;
1311         }
1312
1313         reply_outbuf(req, 0, 0);
1314
1315  path_err:
1316         /* We special case this - as when a Windows machine
1317                 is parsing a path is steps through the components
1318                 one at a time - if a component fails it expects
1319                 ERRbadpath, not ERRbadfile.
1320         */
1321         status = map_checkpath_error(req->flags2, status);
1322         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1323                 /*
1324                  * Windows returns different error codes if
1325                  * the parent directory is valid but not the
1326                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1327                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1328                  * if the path is invalid.
1329                  */
1330                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1331                                 ERRDOS, ERRbadpath);
1332                 goto out;
1333         }
1334
1335         reply_nterror(req, status);
1336
1337  out:
1338         TALLOC_FREE(smb_fname);
1339         END_PROFILE(SMBcheckpath);
1340         return;
1341 }
1342
1343 /****************************************************************************
1344  Reply to a getatr.
1345 ****************************************************************************/
1346
1347 void reply_getatr(struct smb_request *req)
1348 {
1349         connection_struct *conn = req->conn;
1350         struct smb_filename *smb_fname = NULL;
1351         char *fname = NULL;
1352         int mode=0;
1353         off_t size=0;
1354         time_t mtime=0;
1355         const char *p;
1356         NTSTATUS status;
1357         TALLOC_CTX *ctx = talloc_tos();
1358         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1359
1360         START_PROFILE(SMBgetatr);
1361
1362         p = (const char *)req->buf + 1;
1363         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1364         if (!NT_STATUS_IS_OK(status)) {
1365                 reply_nterror(req, status);
1366                 goto out;
1367         }
1368
1369         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1370                 under WfWg - weird! */
1371         if (*fname == '\0') {
1372                 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1373                 if (!CAN_WRITE(conn)) {
1374                         mode |= FILE_ATTRIBUTE_READONLY;
1375                 }
1376                 size = 0;
1377                 mtime = 0;
1378         } else {
1379                 uint32_t ucf_flags = (lp_posix_pathnames() ?
1380                                 UCF_POSIX_PATHNAMES : 0);
1381                 status = filename_convert(ctx,
1382                                 conn,
1383                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1384                                 fname,
1385                                 ucf_flags,
1386                                 NULL,
1387                                 &smb_fname);
1388                 if (!NT_STATUS_IS_OK(status)) {
1389                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1390                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1391                                                 ERRSRV, ERRbadpath);
1392                                 goto out;
1393                         }
1394                         reply_nterror(req, status);
1395                         goto out;
1396                 }
1397                 if (!VALID_STAT(smb_fname->st) &&
1398                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1399                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1400                                  smb_fname_str_dbg(smb_fname),
1401                                  strerror(errno)));
1402                         reply_nterror(req,  map_nt_error_from_unix(errno));
1403                         goto out;
1404                 }
1405
1406                 mode = dos_mode(conn, smb_fname);
1407                 size = smb_fname->st.st_ex_size;
1408
1409                 if (ask_sharemode) {
1410                         struct timespec write_time_ts;
1411                         struct file_id fileid;
1412
1413                         ZERO_STRUCT(write_time_ts);
1414                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1415                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1416                         if (!null_timespec(write_time_ts)) {
1417                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1418                         }
1419                 }
1420
1421                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1422                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1423                         size = 0;
1424                 }
1425         }
1426
1427         reply_outbuf(req, 10, 0);
1428
1429         SSVAL(req->outbuf,smb_vwv0,mode);
1430         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1431                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1432         } else {
1433                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1434         }
1435         SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1436
1437         if (get_Protocol() >= PROTOCOL_NT1) {
1438                 SSVAL(req->outbuf, smb_flg2,
1439                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1440         }
1441
1442         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1443                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1444
1445  out:
1446         TALLOC_FREE(smb_fname);
1447         TALLOC_FREE(fname);
1448         END_PROFILE(SMBgetatr);
1449         return;
1450 }
1451
1452 /****************************************************************************
1453  Reply to a setatr.
1454 ****************************************************************************/
1455
1456 void reply_setatr(struct smb_request *req)
1457 {
1458         struct smb_file_time ft;
1459         connection_struct *conn = req->conn;
1460         struct smb_filename *smb_fname = NULL;
1461         char *fname = NULL;
1462         int mode;
1463         time_t mtime;
1464         const char *p;
1465         NTSTATUS status;
1466         uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1467         TALLOC_CTX *ctx = talloc_tos();
1468
1469         START_PROFILE(SMBsetatr);
1470
1471         ZERO_STRUCT(ft);
1472
1473         if (req->wct < 2) {
1474                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1475                 goto out;
1476         }
1477
1478         p = (const char *)req->buf + 1;
1479         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1480         if (!NT_STATUS_IS_OK(status)) {
1481                 reply_nterror(req, status);
1482                 goto out;
1483         }
1484
1485         status = filename_convert(ctx,
1486                                 conn,
1487                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1488                                 fname,
1489                                 ucf_flags,
1490                                 NULL,
1491                                 &smb_fname);
1492         if (!NT_STATUS_IS_OK(status)) {
1493                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1494                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1495                                         ERRSRV, ERRbadpath);
1496                         goto out;
1497                 }
1498                 reply_nterror(req, status);
1499                 goto out;
1500         }
1501
1502         if (smb_fname->base_name[0] == '.' &&
1503             smb_fname->base_name[1] == '\0') {
1504                 /*
1505                  * Not sure here is the right place to catch this
1506                  * condition. Might be moved to somewhere else later -- vl
1507                  */
1508                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1509                 goto out;
1510         }
1511
1512         mode = SVAL(req->vwv+0, 0);
1513         mtime = srv_make_unix_date3(req->vwv+1);
1514
1515         if (mode != FILE_ATTRIBUTE_NORMAL) {
1516                 if (VALID_STAT_OF_DIR(smb_fname->st))
1517                         mode |= FILE_ATTRIBUTE_DIRECTORY;
1518                 else
1519                         mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1520
1521                 status = check_access(conn, NULL, smb_fname,
1522                                         FILE_WRITE_ATTRIBUTES);
1523                 if (!NT_STATUS_IS_OK(status)) {
1524                         reply_nterror(req, status);
1525                         goto out;
1526                 }
1527
1528                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1529                                      false) != 0) {
1530                         reply_nterror(req, map_nt_error_from_unix(errno));
1531                         goto out;
1532                 }
1533         }
1534
1535         ft.mtime = convert_time_t_to_timespec(mtime);
1536         status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1537         if (!NT_STATUS_IS_OK(status)) {
1538                 reply_nterror(req, status);
1539                 goto out;
1540         }
1541
1542         reply_outbuf(req, 0, 0);
1543
1544         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1545                  mode));
1546  out:
1547         TALLOC_FREE(smb_fname);
1548         END_PROFILE(SMBsetatr);
1549         return;
1550 }
1551
1552 /****************************************************************************
1553  Reply to a dskattr.
1554 ****************************************************************************/
1555
1556 void reply_dskattr(struct smb_request *req)
1557 {
1558         connection_struct *conn = req->conn;
1559         uint64_t ret;
1560         uint64_t dfree,dsize,bsize;
1561         START_PROFILE(SMBdskattr);
1562
1563         ret = get_dfree_info(conn, ".", &bsize, &dfree, &dsize);
1564         if (ret == (uint64_t)-1) {
1565                 reply_nterror(req, map_nt_error_from_unix(errno));
1566                 END_PROFILE(SMBdskattr);
1567                 return;
1568         }
1569
1570         /*
1571          * Force max to fit in 16 bit fields.
1572          */
1573         while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1574                 dfree /= 2;
1575                 dsize /= 2;
1576                 bsize *= 2;
1577                 if (bsize > (WORDMAX*512)) {
1578                         bsize = (WORDMAX*512);
1579                         if (dsize > WORDMAX)
1580                                 dsize = WORDMAX;
1581                         if (dfree >  WORDMAX)
1582                                 dfree = WORDMAX;
1583                         break;
1584                 }
1585         }
1586
1587         reply_outbuf(req, 5, 0);
1588
1589         if (get_Protocol() <= PROTOCOL_LANMAN2) {
1590                 double total_space, free_space;
1591                 /* we need to scale this to a number that DOS6 can handle. We
1592                    use floating point so we can handle large drives on systems
1593                    that don't have 64 bit integers 
1594
1595                    we end up displaying a maximum of 2G to DOS systems
1596                 */
1597                 total_space = dsize * (double)bsize;
1598                 free_space = dfree * (double)bsize;
1599
1600                 dsize = (uint64_t)((total_space+63*512) / (64*512));
1601                 dfree = (uint64_t)((free_space+63*512) / (64*512));
1602
1603                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1604                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1605
1606                 SSVAL(req->outbuf,smb_vwv0,dsize);
1607                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1608                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1609                 SSVAL(req->outbuf,smb_vwv3,dfree);
1610         } else {
1611                 SSVAL(req->outbuf,smb_vwv0,dsize);
1612                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1613                 SSVAL(req->outbuf,smb_vwv2,512);
1614                 SSVAL(req->outbuf,smb_vwv3,dfree);
1615         }
1616
1617         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1618
1619         END_PROFILE(SMBdskattr);
1620         return;
1621 }
1622
1623 /*
1624  * Utility function to split the filename from the directory.
1625  */
1626 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1627                                      char **fname_dir_out,
1628                                      char **fname_mask_out)
1629 {
1630         const char *p = NULL;
1631         char *fname_dir = NULL;
1632         char *fname_mask = NULL;
1633
1634         p = strrchr_m(fname_in, '/');
1635         if (!p) {
1636                 fname_dir = talloc_strdup(ctx, ".");
1637                 fname_mask = talloc_strdup(ctx, fname_in);
1638         } else {
1639                 fname_dir = talloc_strndup(ctx, fname_in,
1640                     PTR_DIFF(p, fname_in));
1641                 fname_mask = talloc_strdup(ctx, p+1);
1642         }
1643
1644         if (!fname_dir || !fname_mask) {
1645                 TALLOC_FREE(fname_dir);
1646                 TALLOC_FREE(fname_mask);
1647                 return NT_STATUS_NO_MEMORY;
1648         }
1649
1650         *fname_dir_out = fname_dir;
1651         *fname_mask_out = fname_mask;
1652         return NT_STATUS_OK;
1653 }
1654
1655 /****************************************************************************
1656  Make a dir struct.
1657 ****************************************************************************/
1658
1659 static bool make_dir_struct(TALLOC_CTX *ctx,
1660                             char *buf,
1661                             const char *mask,
1662                             const char *fname,
1663                             off_t size,
1664                             uint32_t mode,
1665                             time_t date,
1666                             bool uc)
1667 {
1668         char *p;
1669         char *mask2 = talloc_strdup(ctx, mask);
1670
1671         if (!mask2) {
1672                 return False;
1673         }
1674
1675         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1676                 size = 0;
1677         }
1678
1679         memset(buf+1,' ',11);
1680         if ((p = strchr_m(mask2,'.')) != NULL) {
1681                 *p = 0;
1682                 push_ascii(buf+1,mask2,8, 0);
1683                 push_ascii(buf+9,p+1,3, 0);
1684                 *p = '.';
1685         } else {
1686                 push_ascii(buf+1,mask2,11, 0);
1687         }
1688
1689         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1690         SCVAL(buf,21,mode);
1691         srv_put_dos_date(buf,22,date);
1692         SSVAL(buf,26,size & 0xFFFF);
1693         SSVAL(buf,28,(size >> 16)&0xFFFF);
1694         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1695            Strange, but verified on W2K3. Needed for OS/2. JRA. */
1696         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1697         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1698         return True;
1699 }
1700
1701 /****************************************************************************
1702  Reply to a search.
1703  Can be called from SMBsearch, SMBffirst or SMBfunique.
1704 ****************************************************************************/
1705
1706 void reply_search(struct smb_request *req)
1707 {
1708         connection_struct *conn = req->conn;
1709         char *path = NULL;
1710         char *mask = NULL;
1711         char *directory = NULL;
1712         struct smb_filename *smb_fname = NULL;
1713         char *fname = NULL;
1714         off_t size;
1715         uint32_t mode;
1716         struct timespec date;
1717         uint32_t dirtype;
1718         unsigned int numentries = 0;
1719         unsigned int maxentries = 0;
1720         bool finished = False;
1721         const char *p;
1722         int status_len;
1723         char status[21];
1724         int dptr_num= -1;
1725         bool check_descend = False;
1726         bool expect_close = False;
1727         NTSTATUS nt_status;
1728         bool mask_contains_wcard = False;
1729         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1730         TALLOC_CTX *ctx = talloc_tos();
1731         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1732         struct dptr_struct *dirptr = NULL;
1733         struct smbXsrv_connection *xconn = req->xconn;
1734         struct smbd_server_connection *sconn = req->sconn;
1735
1736         START_PROFILE(SMBsearch);
1737
1738         if (req->wct < 2) {
1739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1740                 goto out;
1741         }
1742
1743         if (lp_posix_pathnames()) {
1744                 reply_unknown_new(req, req->cmd);
1745                 goto out;
1746         }
1747
1748         /* If we were called as SMBffirst then we must expect close. */
1749         if(req->cmd == SMBffirst) {
1750                 expect_close = True;
1751         }
1752
1753         reply_outbuf(req, 1, 3);
1754         maxentries = SVAL(req->vwv+0, 0);
1755         dirtype = SVAL(req->vwv+1, 0);
1756         p = (const char *)req->buf + 1;
1757         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1758                                        &nt_status, &mask_contains_wcard);
1759         if (!NT_STATUS_IS_OK(nt_status)) {
1760                 reply_nterror(req, nt_status);
1761                 goto out;
1762         }
1763
1764         p++;
1765         status_len = SVAL(p, 0);
1766         p += 2;
1767
1768         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1769
1770         if (status_len == 0) {
1771                 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1772                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1773                 nt_status = filename_convert(ctx, conn,
1774                                              req->flags2 & FLAGS2_DFS_PATHNAMES,
1775                                              path,
1776                                              ucf_flags,
1777                                              &mask_contains_wcard,
1778                                              &smb_fname);
1779                 if (!NT_STATUS_IS_OK(nt_status)) {
1780                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1781                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1782                                                 ERRSRV, ERRbadpath);
1783                                 goto out;
1784                         }
1785                         reply_nterror(req, nt_status);
1786                         goto out;
1787                 }
1788
1789                 directory = smb_fname->base_name;
1790
1791                 p = strrchr_m(directory,'/');
1792                 if ((p != NULL) && (*directory != '/')) {
1793                         mask = talloc_strdup(ctx, p + 1);
1794                         directory = talloc_strndup(ctx, directory,
1795                                                    PTR_DIFF(p, directory));
1796                 } else {
1797                         mask = talloc_strdup(ctx, directory);
1798                         directory = talloc_strdup(ctx,".");
1799                 }
1800
1801                 if (!directory) {
1802                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1803                         goto out;
1804                 }
1805
1806                 memset((char *)status,'\0',21);
1807                 SCVAL(status,0,(dirtype & 0x1F));
1808
1809                 nt_status = dptr_create(conn,
1810                                         NULL, /* req */
1811                                         NULL, /* fsp */
1812                                         directory,
1813                                         True,
1814                                         expect_close,
1815                                         req->smbpid,
1816                                         mask,
1817                                         mask_contains_wcard,
1818                                         dirtype,
1819                                         &dirptr);
1820                 if (!NT_STATUS_IS_OK(nt_status)) {
1821                         reply_nterror(req, nt_status);
1822                         goto out;
1823                 }
1824                 dptr_num = dptr_dnum(dirptr);
1825         } else {
1826                 int status_dirtype;
1827                 const char *dirpath;
1828
1829                 memcpy(status,p,21);
1830                 status_dirtype = CVAL(status,0) & 0x1F;
1831                 if (status_dirtype != (dirtype & 0x1F)) {
1832                         dirtype = status_dirtype;
1833                 }
1834
1835                 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1836                 if (!dirptr) {
1837                         goto SearchEmpty;
1838                 }
1839                 dirpath = dptr_path(sconn, dptr_num);
1840                 directory = talloc_strdup(ctx, dirpath);
1841                 if (!directory) {
1842                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1843                         goto out;
1844                 }
1845
1846                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1847                 if (!mask) {
1848                         goto SearchEmpty;
1849                 }
1850                 /*
1851                  * For a 'continue' search we have no string. So
1852                  * check from the initial saved string.
1853                  */
1854                 if (!lp_posix_pathnames()) {
1855                         mask_contains_wcard = ms_has_wild(mask);
1856                 }
1857                 dirtype = dptr_attr(sconn, dptr_num);
1858         }
1859
1860         DEBUG(4,("dptr_num is %d\n",dptr_num));
1861
1862         /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1863         dptr_init_search_op(dirptr);
1864
1865         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1866                 char buf[DIR_STRUCT_SIZE];
1867                 memcpy(buf,status,21);
1868                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1869                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1870                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1871                         goto out;
1872                 }
1873                 dptr_fill(sconn, buf+12,dptr_num);
1874                 if (dptr_zero(buf+12) && (status_len==0)) {
1875                         numentries = 1;
1876                 } else {
1877                         numentries = 0;
1878                 }
1879                 if (message_push_blob(&req->outbuf,
1880                                       data_blob_const(buf, sizeof(buf)))
1881                     == -1) {
1882                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1883                         goto out;
1884                 }
1885         } else {
1886                 unsigned int i;
1887                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1888                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1889
1890                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1891
1892                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1893                          directory,lp_dont_descend(ctx, SNUM(conn))));
1894                 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1895                         check_descend = True;
1896                 }
1897
1898                 for (i=numentries;(i<maxentries) && !finished;i++) {
1899                         finished = !get_dir_entry(ctx,
1900                                                   dirptr,
1901                                                   mask,
1902                                                   dirtype,
1903                                                   &fname,
1904                                                   &size,
1905                                                   &mode,
1906                                                   &date,
1907                                                   check_descend,
1908                                                   ask_sharemode);
1909                         if (!finished) {
1910                                 char buf[DIR_STRUCT_SIZE];
1911                                 memcpy(buf,status,21);
1912                                 if (!make_dir_struct(ctx,
1913                                                 buf,
1914                                                 mask,
1915                                                 fname,
1916                                                 size,
1917                                                 mode,
1918                                                 convert_timespec_to_time_t(date),
1919                                                 !allow_long_path_components)) {
1920                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1921                                         goto out;
1922                                 }
1923                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1924                                         break;
1925                                 }
1926                                 if (message_push_blob(&req->outbuf,
1927                                                       data_blob_const(buf, sizeof(buf)))
1928                                     == -1) {
1929                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1930                                         goto out;
1931                                 }
1932                                 numentries++;
1933                         }
1934                 }
1935         }
1936
1937   SearchEmpty:
1938
1939         /* If we were called as SMBffirst with smb_search_id == NULL
1940                 and no entries were found then return error and close dirptr 
1941                 (X/Open spec) */
1942
1943         if (numentries == 0) {
1944                 dptr_close(sconn, &dptr_num);
1945         } else if(expect_close && status_len == 0) {
1946                 /* Close the dptr - we know it's gone */
1947                 dptr_close(sconn, &dptr_num);
1948         }
1949
1950         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1951         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1952                 dptr_close(sconn, &dptr_num);
1953         }
1954
1955         if ((numentries == 0) && !mask_contains_wcard) {
1956                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1957                 goto out;
1958         }
1959
1960         SSVAL(req->outbuf,smb_vwv0,numentries);
1961         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1962         SCVAL(smb_buf(req->outbuf),0,5);
1963         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1964
1965         /* The replies here are never long name. */
1966         SSVAL(req->outbuf, smb_flg2,
1967               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1968         if (!allow_long_path_components) {
1969                 SSVAL(req->outbuf, smb_flg2,
1970                       SVAL(req->outbuf, smb_flg2)
1971                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1972         }
1973
1974         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1975         SSVAL(req->outbuf, smb_flg2,
1976               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1977
1978         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1979                 smb_fn_name(req->cmd),
1980                 mask,
1981                 directory,
1982                 dirtype,
1983                 numentries,
1984                 maxentries ));
1985  out:
1986         TALLOC_FREE(directory);
1987         TALLOC_FREE(mask);
1988         TALLOC_FREE(smb_fname);
1989         END_PROFILE(SMBsearch);
1990         return;
1991 }
1992
1993 /****************************************************************************
1994  Reply to a fclose (stop directory search).
1995 ****************************************************************************/
1996
1997 void reply_fclose(struct smb_request *req)
1998 {
1999         int status_len;
2000         char status[21];
2001         int dptr_num= -2;
2002         const char *p;
2003         char *path = NULL;
2004         NTSTATUS err;
2005         bool path_contains_wcard = False;
2006         TALLOC_CTX *ctx = talloc_tos();
2007         struct smbd_server_connection *sconn = req->sconn;
2008
2009         START_PROFILE(SMBfclose);
2010
2011         if (lp_posix_pathnames()) {
2012                 reply_unknown_new(req, req->cmd);
2013                 END_PROFILE(SMBfclose);
2014                 return;
2015         }
2016
2017         p = (const char *)req->buf + 1;
2018         p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2019                                        &err, &path_contains_wcard);
2020         if (!NT_STATUS_IS_OK(err)) {
2021                 reply_nterror(req, err);
2022                 END_PROFILE(SMBfclose);
2023                 return;
2024         }
2025         p++;
2026         status_len = SVAL(p,0);
2027         p += 2;
2028
2029         if (status_len == 0) {
2030                 reply_force_doserror(req, ERRSRV, ERRsrverror);
2031                 END_PROFILE(SMBfclose);
2032                 return;
2033         }
2034
2035         memcpy(status,p,21);
2036
2037         if(dptr_fetch(sconn, status+12,&dptr_num)) {
2038                 /*  Close the dptr - we know it's gone */
2039                 dptr_close(sconn, &dptr_num);
2040         }
2041
2042         reply_outbuf(req, 1, 0);
2043         SSVAL(req->outbuf,smb_vwv0,0);
2044
2045         DEBUG(3,("search close\n"));
2046
2047         END_PROFILE(SMBfclose);
2048         return;
2049 }
2050
2051 /****************************************************************************
2052  Reply to an open.
2053 ****************************************************************************/
2054
2055 void reply_open(struct smb_request *req)
2056 {
2057         connection_struct *conn = req->conn;
2058         struct smb_filename *smb_fname = NULL;
2059         char *fname = NULL;
2060         uint32_t fattr=0;
2061         off_t size = 0;
2062         time_t mtime=0;
2063         int info;
2064         files_struct *fsp;
2065         int oplock_request;
2066         int deny_mode;
2067         uint32_t dos_attr;
2068         uint32_t access_mask;
2069         uint32_t share_mode;
2070         uint32_t create_disposition;
2071         uint32_t create_options = 0;
2072         uint32_t private_flags = 0;
2073         NTSTATUS status;
2074         uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2075                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2076         TALLOC_CTX *ctx = talloc_tos();
2077
2078         START_PROFILE(SMBopen);
2079
2080         if (req->wct < 2) {
2081                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2082                 goto out;
2083         }
2084
2085         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2086         deny_mode = SVAL(req->vwv+0, 0);
2087         dos_attr = SVAL(req->vwv+1, 0);
2088
2089         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2090                             STR_TERMINATE, &status);
2091         if (!NT_STATUS_IS_OK(status)) {
2092                 reply_nterror(req, status);
2093                 goto out;
2094         }
2095
2096         if (!map_open_params_to_ntcreate(fname, deny_mode,
2097                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
2098                                          &share_mode, &create_disposition,
2099                                          &create_options, &private_flags)) {
2100                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2101                 goto out;
2102         }
2103
2104         status = filename_convert(ctx,
2105                                 conn,
2106                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2107                                 fname,
2108                                 ucf_flags,
2109                                 NULL,
2110                                 &smb_fname);
2111         if (!NT_STATUS_IS_OK(status)) {
2112                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2113                         reply_botherror(req,
2114                                         NT_STATUS_PATH_NOT_COVERED,
2115                                         ERRSRV, ERRbadpath);
2116                         goto out;
2117                 }
2118                 reply_nterror(req, status);
2119                 goto out;
2120         }
2121
2122         status = SMB_VFS_CREATE_FILE(
2123                 conn,                                   /* conn */
2124                 req,                                    /* req */
2125                 0,                                      /* root_dir_fid */
2126                 smb_fname,                              /* fname */
2127                 access_mask,                            /* access_mask */
2128                 share_mode,                             /* share_access */
2129                 create_disposition,                     /* create_disposition*/
2130                 create_options,                         /* create_options */
2131                 dos_attr,                               /* file_attributes */
2132                 oplock_request,                         /* oplock_request */
2133                 NULL,                                   /* lease */
2134                 0,                                      /* allocation_size */
2135                 private_flags,
2136                 NULL,                                   /* sd */
2137                 NULL,                                   /* ea_list */
2138                 &fsp,                                   /* result */
2139                 &info,                                  /* pinfo */
2140                 NULL, NULL);                            /* create context */
2141
2142         if (!NT_STATUS_IS_OK(status)) {
2143                 if (open_was_deferred(req->xconn, req->mid)) {
2144                         /* We have re-scheduled this call. */
2145                         goto out;
2146                 }
2147                 reply_openerror(req, status);
2148                 goto out;
2149         }
2150
2151         /* Ensure we're pointing at the correct stat struct. */
2152         TALLOC_FREE(smb_fname);
2153         smb_fname = fsp->fsp_name;
2154
2155         size = smb_fname->st.st_ex_size;
2156         fattr = dos_mode(conn, smb_fname);
2157
2158         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2159
2160         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2161                 DEBUG(3,("attempt to open a directory %s\n",
2162                          fsp_str_dbg(fsp)));
2163                 close_file(req, fsp, ERROR_CLOSE);
2164                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2165                         ERRDOS, ERRnoaccess);
2166                 goto out;
2167         }
2168
2169         reply_outbuf(req, 7, 0);
2170         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2171         SSVAL(req->outbuf,smb_vwv1,fattr);
2172         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2173                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2174         } else {
2175                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2176         }
2177         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2178         SSVAL(req->outbuf,smb_vwv6,deny_mode);
2179
2180         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2181                 SCVAL(req->outbuf,smb_flg,
2182                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2183         }
2184
2185         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2186                 SCVAL(req->outbuf,smb_flg,
2187                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2188         }
2189  out:
2190         END_PROFILE(SMBopen);
2191         return;
2192 }
2193
2194 /****************************************************************************
2195  Reply to an open and X.
2196 ****************************************************************************/
2197
2198 void reply_open_and_X(struct smb_request *req)
2199 {
2200         connection_struct *conn = req->conn;
2201         struct smb_filename *smb_fname = NULL;
2202         char *fname = NULL;
2203         uint16_t open_flags;
2204         int deny_mode;
2205         uint32_t smb_attr;
2206         /* Breakout the oplock request bits so we can set the
2207                 reply bits separately. */
2208         int ex_oplock_request;
2209         int core_oplock_request;
2210         int oplock_request;
2211 #if 0
2212         int smb_sattr = SVAL(req->vwv+4, 0);
2213         uint32_t smb_time = make_unix_date3(req->vwv+6);
2214 #endif
2215         int smb_ofun;
2216         uint32_t fattr=0;
2217         int mtime=0;
2218         int smb_action = 0;
2219         files_struct *fsp;
2220         NTSTATUS status;
2221         uint64_t allocation_size;
2222         ssize_t retval = -1;
2223         uint32_t access_mask;
2224         uint32_t share_mode;
2225         uint32_t create_disposition;
2226         uint32_t create_options = 0;
2227         uint32_t private_flags = 0;
2228         uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2229                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2230         TALLOC_CTX *ctx = talloc_tos();
2231
2232         START_PROFILE(SMBopenX);
2233
2234         if (req->wct < 15) {
2235                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2236                 goto out;
2237         }
2238
2239         open_flags = SVAL(req->vwv+2, 0);
2240         deny_mode = SVAL(req->vwv+3, 0);
2241         smb_attr = SVAL(req->vwv+5, 0);
2242         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2243         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2244         oplock_request = ex_oplock_request | core_oplock_request;
2245         smb_ofun = SVAL(req->vwv+8, 0);
2246         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2247
2248         /* If it's an IPC, pass off the pipe handler. */
2249         if (IS_IPC(conn)) {
2250                 if (lp_nt_pipe_support()) {
2251                         reply_open_pipe_and_X(conn, req);
2252                 } else {
2253                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2254                 }
2255                 goto out;
2256         }
2257
2258         /* XXXX we need to handle passed times, sattr and flags */
2259         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2260                         STR_TERMINATE, &status);
2261         if (!NT_STATUS_IS_OK(status)) {
2262                 reply_nterror(req, status);
2263                 goto out;
2264         }
2265
2266         if (!map_open_params_to_ntcreate(fname, deny_mode,
2267                                          smb_ofun,
2268                                          &access_mask, &share_mode,
2269                                          &create_disposition,
2270                                          &create_options,
2271                                          &private_flags)) {
2272                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2273                 goto out;
2274         }
2275
2276         status = filename_convert(ctx,
2277                                 conn,
2278                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2279                                 fname,
2280                                 ucf_flags,
2281                                 NULL,
2282                                 &smb_fname);
2283         if (!NT_STATUS_IS_OK(status)) {
2284                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2285                         reply_botherror(req,
2286                                         NT_STATUS_PATH_NOT_COVERED,
2287                                         ERRSRV, ERRbadpath);
2288                         goto out;
2289                 }
2290                 reply_nterror(req, status);
2291                 goto out;
2292         }
2293
2294         status = SMB_VFS_CREATE_FILE(
2295                 conn,                                   /* conn */
2296                 req,                                    /* req */
2297                 0,                                      /* root_dir_fid */
2298                 smb_fname,                              /* fname */
2299                 access_mask,                            /* access_mask */
2300                 share_mode,                             /* share_access */
2301                 create_disposition,                     /* create_disposition*/
2302                 create_options,                         /* create_options */
2303                 smb_attr,                               /* file_attributes */
2304                 oplock_request,                         /* oplock_request */
2305                 NULL,                                   /* lease */
2306                 0,                                      /* allocation_size */
2307                 private_flags,
2308                 NULL,                                   /* sd */
2309                 NULL,                                   /* ea_list */
2310                 &fsp,                                   /* result */
2311                 &smb_action,                            /* pinfo */
2312                 NULL, NULL);                            /* create context */
2313
2314         if (!NT_STATUS_IS_OK(status)) {
2315                 if (open_was_deferred(req->xconn, req->mid)) {
2316                         /* We have re-scheduled this call. */
2317                         goto out;
2318                 }
2319                 reply_openerror(req, status);
2320                 goto out;
2321         }
2322
2323         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2324            if the file is truncated or created. */
2325         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2326                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2327                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2328                         close_file(req, fsp, ERROR_CLOSE);
2329                         reply_nterror(req, NT_STATUS_DISK_FULL);
2330                         goto out;
2331                 }
2332                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2333                 if (retval < 0) {
2334                         close_file(req, fsp, ERROR_CLOSE);
2335                         reply_nterror(req, NT_STATUS_DISK_FULL);
2336                         goto out;
2337                 }
2338                 status = vfs_stat_fsp(fsp);
2339                 if (!NT_STATUS_IS_OK(status)) {
2340                         close_file(req, fsp, ERROR_CLOSE);
2341                         reply_nterror(req, status);
2342                         goto out;
2343                 }
2344         }
2345
2346         fattr = dos_mode(conn, fsp->fsp_name);
2347         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2348         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2349                 close_file(req, fsp, ERROR_CLOSE);
2350                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2351                 goto out;
2352         }
2353
2354         /* If the caller set the extended oplock request bit
2355                 and we granted one (by whatever means) - set the
2356                 correct bit for extended oplock reply.
2357         */
2358
2359         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2360                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2361         }
2362
2363         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2364                 smb_action |= EXTENDED_OPLOCK_GRANTED;
2365         }
2366
2367         /* If the caller set the core oplock request bit
2368                 and we granted one (by whatever means) - set the
2369                 correct bit for core oplock reply.
2370         */
2371
2372         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2373                 reply_outbuf(req, 19, 0);
2374         } else {
2375                 reply_outbuf(req, 15, 0);
2376         }
2377
2378         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2379         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2380
2381         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2382                 SCVAL(req->outbuf, smb_flg,
2383                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2384         }
2385
2386         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2387                 SCVAL(req->outbuf, smb_flg,
2388                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2389         }
2390
2391         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2392         SSVAL(req->outbuf,smb_vwv3,fattr);
2393         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2394                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2395         } else {
2396                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2397         }
2398         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2399         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2400         SSVAL(req->outbuf,smb_vwv11,smb_action);
2401
2402         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2403                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2404         }
2405
2406  out:
2407         TALLOC_FREE(smb_fname);
2408         END_PROFILE(SMBopenX);
2409         return;
2410 }
2411
2412 /****************************************************************************
2413  Reply to a SMBulogoffX.
2414 ****************************************************************************/
2415
2416 void reply_ulogoffX(struct smb_request *req)
2417 {
2418         struct smbd_server_connection *sconn = req->sconn;
2419         struct user_struct *vuser;
2420         struct smbXsrv_session *session = NULL;
2421         NTSTATUS status;
2422
2423         START_PROFILE(SMBulogoffX);
2424
2425         vuser = get_valid_user_struct(sconn, req->vuid);
2426
2427         if(vuser == NULL) {
2428                 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2429                          (unsigned long long)req->vuid));
2430
2431                 req->vuid = UID_FIELD_INVALID;
2432                 reply_force_doserror(req, ERRSRV, ERRbaduid);
2433                 END_PROFILE(SMBulogoffX);
2434                 return;
2435         }
2436
2437         session = vuser->session;
2438         vuser = NULL;
2439
2440         /*
2441          * TODO: cancel all outstanding requests on the session
2442          */
2443         status = smbXsrv_session_logoff(session);
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 DEBUG(0, ("reply_ulogoff: "
2446                           "smbXsrv_session_logoff() failed: %s\n",
2447                           nt_errstr(status)));
2448                 /*
2449                  * If we hit this case, there is something completely
2450                  * wrong, so we better disconnect the transport connection.
2451                  */
2452                 END_PROFILE(SMBulogoffX);
2453                 exit_server(__location__ ": smbXsrv_session_logoff failed");
2454                 return;
2455         }
2456
2457         TALLOC_FREE(session);
2458
2459         reply_outbuf(req, 2, 0);
2460         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2461         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2462
2463         DEBUG(3, ("ulogoffX vuid=%llu\n",
2464                   (unsigned long long)req->vuid));
2465
2466         END_PROFILE(SMBulogoffX);
2467         req->vuid = UID_FIELD_INVALID;
2468 }
2469
2470 /****************************************************************************
2471  Reply to a mknew or a create.
2472 ****************************************************************************/
2473
2474 void reply_mknew(struct smb_request *req)
2475 {
2476         connection_struct *conn = req->conn;
2477         struct smb_filename *smb_fname = NULL;
2478         char *fname = NULL;
2479         uint32_t fattr = 0;
2480         struct smb_file_time ft;
2481         files_struct *fsp;
2482         int oplock_request = 0;
2483         NTSTATUS status;
2484         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2485         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2486         uint32_t create_disposition;
2487         uint32_t create_options = 0;
2488         uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2489                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2490         TALLOC_CTX *ctx = talloc_tos();
2491
2492         START_PROFILE(SMBcreate);
2493         ZERO_STRUCT(ft);
2494
2495         if (req->wct < 3) {
2496                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2497                 goto out;
2498         }
2499
2500         fattr = SVAL(req->vwv+0, 0);
2501         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2502
2503         /* mtime. */
2504         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2505
2506         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2507                             STR_TERMINATE, &status);
2508         if (!NT_STATUS_IS_OK(status)) {
2509                 reply_nterror(req, status);
2510                 goto out;
2511         }
2512
2513         status = filename_convert(ctx,
2514                                 conn,
2515                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2516                                 fname,
2517                                 ucf_flags,
2518                                 NULL,
2519                                 &smb_fname);
2520         if (!NT_STATUS_IS_OK(status)) {
2521                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2522                         reply_botherror(req,
2523                                         NT_STATUS_PATH_NOT_COVERED,
2524                                         ERRSRV, ERRbadpath);
2525                         goto out;
2526                 }
2527                 reply_nterror(req, status);
2528                 goto out;
2529         }
2530
2531         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2532                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2533                          "please report this\n",
2534                          smb_fname_str_dbg(smb_fname)));
2535         }
2536
2537         if(req->cmd == SMBmknew) {
2538                 /* We should fail if file exists. */
2539                 create_disposition = FILE_CREATE;
2540         } else {
2541                 /* Create if file doesn't exist, truncate if it does. */
2542                 create_disposition = FILE_OVERWRITE_IF;
2543         }
2544
2545         status = SMB_VFS_CREATE_FILE(
2546                 conn,                                   /* conn */
2547                 req,                                    /* req */
2548                 0,                                      /* root_dir_fid */
2549                 smb_fname,                              /* fname */
2550                 access_mask,                            /* access_mask */
2551                 share_mode,                             /* share_access */
2552                 create_disposition,                     /* create_disposition*/
2553                 create_options,                         /* create_options */
2554                 fattr,                                  /* file_attributes */
2555                 oplock_request,                         /* oplock_request */
2556                 NULL,                                   /* lease */
2557                 0,                                      /* allocation_size */
2558                 0,                                      /* private_flags */
2559                 NULL,                                   /* sd */
2560                 NULL,                                   /* ea_list */
2561                 &fsp,                                   /* result */
2562                 NULL,                                   /* pinfo */
2563                 NULL, NULL);                            /* create context */
2564
2565         if (!NT_STATUS_IS_OK(status)) {
2566                 if (open_was_deferred(req->xconn, req->mid)) {
2567                         /* We have re-scheduled this call. */
2568                         goto out;
2569                 }
2570                 reply_openerror(req, status);
2571                 goto out;
2572         }
2573
2574         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2575         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 END_PROFILE(SMBcreate);
2578                 goto out;
2579         }
2580
2581         reply_outbuf(req, 1, 0);
2582         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2583
2584         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2585                 SCVAL(req->outbuf,smb_flg,
2586                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2587         }
2588
2589         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2590                 SCVAL(req->outbuf,smb_flg,
2591                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2592         }
2593
2594         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2595         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2596                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2597                   (unsigned int)fattr));
2598
2599  out:
2600         TALLOC_FREE(smb_fname);
2601         END_PROFILE(SMBcreate);
2602         return;
2603 }
2604
2605 /****************************************************************************
2606  Reply to a create temporary file.
2607 ****************************************************************************/
2608
2609 void reply_ctemp(struct smb_request *req)
2610 {
2611         connection_struct *conn = req->conn;
2612         struct smb_filename *smb_fname = NULL;
2613         char *wire_name = NULL;
2614         char *fname = NULL;
2615         uint32_t fattr;
2616         files_struct *fsp;
2617         int oplock_request;
2618         char *s;
2619         NTSTATUS status;
2620         int i;
2621         uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2622                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2623         TALLOC_CTX *ctx = talloc_tos();
2624
2625         START_PROFILE(SMBctemp);
2626
2627         if (req->wct < 3) {
2628                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2629                 goto out;
2630         }
2631
2632         fattr = SVAL(req->vwv+0, 0);
2633         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2634
2635         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2636                             STR_TERMINATE, &status);
2637         if (!NT_STATUS_IS_OK(status)) {
2638                 reply_nterror(req, status);
2639                 goto out;
2640         }
2641
2642         for (i = 0; i < 10; i++) {
2643                 if (*wire_name) {
2644                         fname = talloc_asprintf(ctx,
2645                                         "%s/TMP%s",
2646                                         wire_name,
2647                                         generate_random_str_list(ctx, 5, "0123456789"));
2648                 } else {
2649                         fname = talloc_asprintf(ctx,
2650                                         "TMP%s",
2651                                         generate_random_str_list(ctx, 5, "0123456789"));
2652                 }
2653
2654                 if (!fname) {
2655                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2656                         goto out;
2657                 }
2658
2659                 status = filename_convert(ctx, conn,
2660                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2661                                 fname,
2662                                 ucf_flags,
2663                                 NULL,
2664                                 &smb_fname);
2665                 if (!NT_STATUS_IS_OK(status)) {
2666                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2667                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2668                                         ERRSRV, ERRbadpath);
2669                                 goto out;
2670                         }
2671                         reply_nterror(req, status);
2672                         goto out;
2673                 }
2674
2675                 /* Create the file. */
2676                 status = SMB_VFS_CREATE_FILE(
2677                         conn,                                   /* conn */
2678                         req,                                    /* req */
2679                         0,                                      /* root_dir_fid */
2680                         smb_fname,                              /* fname */
2681                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2682                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2683                         FILE_CREATE,                            /* create_disposition*/
2684                         0,                                      /* create_options */
2685                         fattr,                                  /* file_attributes */
2686                         oplock_request,                         /* oplock_request */
2687                         NULL,                                   /* lease */
2688                         0,                                      /* allocation_size */
2689                         0,                                      /* private_flags */
2690                         NULL,                                   /* sd */
2691                         NULL,                                   /* ea_list */
2692                         &fsp,                                   /* result */
2693                         NULL,                                   /* pinfo */
2694                         NULL, NULL);                            /* create context */
2695
2696                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2697                         TALLOC_FREE(fname);
2698                         TALLOC_FREE(smb_fname);
2699                         continue;
2700                 }
2701
2702                 if (!NT_STATUS_IS_OK(status)) {
2703                         if (open_was_deferred(req->xconn, req->mid)) {
2704                                 /* We have re-scheduled this call. */
2705                                 goto out;
2706                         }
2707                         reply_openerror(req, status);
2708                         goto out;
2709                 }
2710
2711                 break;
2712         }
2713
2714         if (i == 10) {
2715                 /* Collision after 10 times... */
2716                 reply_nterror(req, status);
2717                 goto out;
2718         }
2719
2720         reply_outbuf(req, 1, 0);
2721         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2722
2723         /* the returned filename is relative to the directory */
2724         s = strrchr_m(fsp->fsp_name->base_name, '/');
2725         if (!s) {
2726                 s = fsp->fsp_name->base_name;
2727         } else {
2728                 s++;
2729         }
2730
2731 #if 0
2732         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2733            thing in the byte section. JRA */
2734         SSVALS(p, 0, -1); /* what is this? not in spec */
2735 #endif
2736         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2737             == -1) {
2738                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2739                 goto out;
2740         }
2741
2742         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2743                 SCVAL(req->outbuf, smb_flg,
2744                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2745         }
2746
2747         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2748                 SCVAL(req->outbuf, smb_flg,
2749                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2750         }
2751
2752         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2753         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2754                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2755  out:
2756         TALLOC_FREE(smb_fname);
2757         TALLOC_FREE(wire_name);
2758         END_PROFILE(SMBctemp);
2759         return;
2760 }
2761
2762 /*******************************************************************
2763  Check if a user is allowed to rename a file.
2764 ********************************************************************/
2765
2766 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2767                         uint16_t dirtype)
2768 {
2769         if (!CAN_WRITE(conn)) {
2770                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2771         }
2772
2773         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2774                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2775                 /* Only bother to read the DOS attribute if we might deny the
2776                    rename on the grounds of attribute mismatch. */
2777                 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2778                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2779                         return NT_STATUS_NO_SUCH_FILE;
2780                 }
2781         }
2782
2783         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2784                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2785                         return NT_STATUS_OK;
2786                 }
2787
2788                 /* If no pathnames are open below this
2789                    directory, allow the rename. */
2790
2791                 if (lp_strict_rename(SNUM(conn))) {
2792                         /*
2793                          * Strict rename, check open file db.
2794                          */
2795                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2796                                 return NT_STATUS_ACCESS_DENIED;
2797                         }
2798                 } else if (file_find_subpath(fsp)) {
2799                         /*
2800                          * No strict rename, just look in local process.
2801                          */
2802                         return NT_STATUS_ACCESS_DENIED;
2803                 }
2804                 return NT_STATUS_OK;
2805         }
2806
2807         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2808                 return NT_STATUS_OK;
2809         }
2810
2811         return NT_STATUS_ACCESS_DENIED;
2812 }
2813
2814 /*******************************************************************
2815  * unlink a file with all relevant access checks
2816  *******************************************************************/
2817
2818 static NTSTATUS do_unlink(connection_struct *conn,
2819                         struct smb_request *req,
2820                         struct smb_filename *smb_fname,
2821                         uint32_t dirtype)
2822 {
2823         uint32_t fattr;
2824         files_struct *fsp;
2825         uint32_t dirtype_orig = dirtype;
2826         NTSTATUS status;
2827         int ret;
2828         bool posix_paths = lp_posix_pathnames();
2829
2830         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2831                   smb_fname_str_dbg(smb_fname),
2832                   dirtype));
2833
2834         if (!CAN_WRITE(conn)) {
2835                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2836         }
2837
2838         if (posix_paths) {
2839                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2840         } else {
2841                 ret = SMB_VFS_STAT(conn, smb_fname);
2842         }
2843         if (ret != 0) {
2844                 return map_nt_error_from_unix(errno);
2845         }
2846
2847         fattr = dos_mode(conn, smb_fname);
2848
2849         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2850                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2851         }
2852
2853         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2854         if (!dirtype) {
2855                 return NT_STATUS_NO_SUCH_FILE;
2856         }
2857
2858         if (!dir_check_ftype(fattr, dirtype)) {
2859                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2860                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2861                 }
2862                 return NT_STATUS_NO_SUCH_FILE;
2863         }
2864
2865         if (dirtype_orig & 0x8000) {
2866                 /* These will never be set for POSIX. */
2867                 return NT_STATUS_NO_SUCH_FILE;
2868         }
2869
2870 #if 0
2871         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2872                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2873         }
2874
2875         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2876                 return NT_STATUS_NO_SUCH_FILE;
2877         }
2878
2879         if (dirtype & 0xFF00) {
2880                 /* These will never be set for POSIX. */
2881                 return NT_STATUS_NO_SUCH_FILE;
2882         }
2883
2884         dirtype &= 0xFF;
2885         if (!dirtype) {
2886                 return NT_STATUS_NO_SUCH_FILE;
2887         }
2888
2889         /* Can't delete a directory. */
2890         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2891                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2892         }
2893 #endif
2894
2895 #if 0 /* JRATEST */
2896         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2897                 return NT_STATUS_OBJECT_NAME_INVALID;
2898 #endif /* JRATEST */
2899
2900         /* On open checks the open itself will check the share mode, so
2901            don't do it here as we'll get it wrong. */
2902
2903         status = SMB_VFS_CREATE_FILE
2904                 (conn,                  /* conn */
2905                  req,                   /* req */
2906                  0,                     /* root_dir_fid */
2907                  smb_fname,             /* fname */
2908                  DELETE_ACCESS,         /* access_mask */
2909                  FILE_SHARE_NONE,       /* share_access */
2910                  FILE_OPEN,             /* create_disposition*/
2911                  FILE_NON_DIRECTORY_FILE, /* create_options */
2912                                         /* file_attributes */
2913                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2914                                 FILE_ATTRIBUTE_NORMAL,
2915                  0,                     /* oplock_request */
2916                  NULL,                  /* lease */
2917                  0,                     /* allocation_size */
2918                  0,                     /* private_flags */
2919                  NULL,                  /* sd */
2920                  NULL,                  /* ea_list */
2921                  &fsp,                  /* result */
2922                  NULL,                  /* pinfo */
2923                  NULL, NULL);           /* create context */
2924
2925         if (!NT_STATUS_IS_OK(status)) {
2926                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2927                            nt_errstr(status)));
2928                 return status;
2929         }
2930
2931         status = can_set_delete_on_close(fsp, fattr);
2932         if (!NT_STATUS_IS_OK(status)) {
2933                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2934                         "(%s)\n",
2935                         smb_fname_str_dbg(smb_fname),
2936                         nt_errstr(status)));
2937                 close_file(req, fsp, NORMAL_CLOSE);
2938                 return status;
2939         }
2940
2941         /* The set is across all open files on this dev/inode pair. */
2942         if (!set_delete_on_close(fsp, True,
2943                                 conn->session_info->security_token,
2944                                 conn->session_info->unix_token)) {
2945                 close_file(req, fsp, NORMAL_CLOSE);
2946                 return NT_STATUS_ACCESS_DENIED;
2947         }
2948
2949         return close_file(req, fsp, NORMAL_CLOSE);
2950 }
2951
2952 /****************************************************************************
2953  The guts of the unlink command, split out so it may be called by the NT SMB
2954  code.
2955 ****************************************************************************/
2956
2957 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2958                           uint32_t dirtype, struct smb_filename *smb_fname,
2959                           bool has_wild)
2960 {
2961         char *fname_dir = NULL;
2962         char *fname_mask = NULL;
2963         int count=0;
2964         NTSTATUS status = NT_STATUS_OK;
2965         TALLOC_CTX *ctx = talloc_tos();
2966
2967         /* Split up the directory from the filename/mask. */
2968         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2969                                       &fname_dir, &fname_mask);
2970         if (!NT_STATUS_IS_OK(status)) {
2971                 goto out;
2972         }
2973
2974         /*
2975          * We should only check the mangled cache
2976          * here if unix_convert failed. This means
2977          * that the path in 'mask' doesn't exist
2978          * on the file system and so we need to look
2979          * for a possible mangle. This patch from
2980          * Tine Smukavec <valentin.smukavec@hermes.si>.
2981          */
2982
2983         if (!VALID_STAT(smb_fname->st) &&
2984             mangle_is_mangled(fname_mask, conn->params)) {
2985                 char *new_mask = NULL;
2986                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2987                                             &new_mask, conn->params);
2988                 if (new_mask) {
2989                         TALLOC_FREE(fname_mask);
2990                         fname_mask = new_mask;
2991                 }
2992         }
2993
2994         if (!has_wild) {
2995
2996                 /*
2997                  * Only one file needs to be unlinked. Append the mask back
2998                  * onto the directory.
2999                  */
3000                 TALLOC_FREE(smb_fname->base_name);
3001                 if (ISDOT(fname_dir)) {
3002                         /* Ensure we use canonical names on open. */
3003                         smb_fname->base_name = talloc_asprintf(smb_fname,
3004                                                         "%s",
3005                                                         fname_mask);
3006                 } else {
3007                         smb_fname->base_name = talloc_asprintf(smb_fname,
3008                                                         "%s/%s",
3009                                                         fname_dir,
3010                                                         fname_mask);
3011                 }
3012                 if (!smb_fname->base_name) {
3013                         status = NT_STATUS_NO_MEMORY;
3014                         goto out;
3015                 }
3016                 if (dirtype == 0) {
3017                         dirtype = FILE_ATTRIBUTE_NORMAL;
3018                 }
3019
3020                 status = check_name(conn, smb_fname->base_name);
3021                 if (!NT_STATUS_IS_OK(status)) {
3022                         goto out;
3023                 }
3024
3025                 status = do_unlink(conn, req, smb_fname, dirtype);
3026                 if (!NT_STATUS_IS_OK(status)) {
3027                         goto out;
3028                 }
3029
3030                 count++;
3031         } else {
3032                 struct smb_Dir *dir_hnd = NULL;
3033                 long offset = 0;
3034                 const char *dname = NULL;
3035                 char *talloced = NULL;
3036
3037                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3038                         status = NT_STATUS_OBJECT_NAME_INVALID;
3039                         goto out;
3040                 }
3041                 if (dirtype == 0) {
3042                         dirtype = FILE_ATTRIBUTE_NORMAL;
3043                 }
3044
3045                 if (strequal(fname_mask,"????????.???")) {
3046                         TALLOC_FREE(fname_mask);
3047                         fname_mask = talloc_strdup(ctx, "*");
3048                         if (!fname_mask) {
3049                                 status = NT_STATUS_NO_MEMORY;
3050                                 goto out;
3051                         }
3052                 }
3053
3054                 status = check_name(conn, fname_dir);
3055                 if (!NT_STATUS_IS_OK(status)) {
3056                         goto out;
3057                 }
3058
3059                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
3060                                   dirtype);
3061                 if (dir_hnd == NULL) {
3062                         status = map_nt_error_from_unix(errno);
3063                         goto out;
3064                 }
3065
3066                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3067                    the pattern matches against the long name, otherwise the short name 
3068                    We don't implement this yet XXXX
3069                 */
3070
3071                 status = NT_STATUS_NO_SUCH_FILE;
3072
3073                 while ((dname = ReadDirName(dir_hnd, &offset,
3074                                             &smb_fname->st, &talloced))) {
3075                         TALLOC_CTX *frame = talloc_stackframe();
3076
3077                         if (!is_visible_file(conn, fname_dir, dname,
3078                                              &smb_fname->st, true)) {
3079                                 TALLOC_FREE(frame);
3080                                 TALLOC_FREE(talloced);
3081                                 continue;
3082                         }
3083
3084                         /* Quick check for "." and ".." */
3085                         if (ISDOT(dname) || ISDOTDOT(dname)) {
3086                                 TALLOC_FREE(frame);
3087                                 TALLOC_FREE(talloced);
3088                                 continue;
3089                         }
3090
3091                         if(!mask_match(dname, fname_mask,
3092                                        conn->case_sensitive)) {
3093                                 TALLOC_FREE(frame);
3094                                 TALLOC_FREE(talloced);
3095                                 continue;
3096                         }
3097
3098                         TALLOC_FREE(smb_fname->base_name);
3099                         if (ISDOT(fname_dir)) {
3100                                 /* Ensure we use canonical names on open. */
3101                                 smb_fname->base_name =
3102                                         talloc_asprintf(smb_fname, "%s",
3103                                                 dname);
3104                         } else {
3105                                 smb_fname->base_name =
3106                                         talloc_asprintf(smb_fname, "%s/%s",
3107                                                 fname_dir, dname);
3108                         }
3109
3110                         if (!smb_fname->base_name) {
3111                                 TALLOC_FREE(dir_hnd);
3112                                 status = NT_STATUS_NO_MEMORY;
3113                                 TALLOC_FREE(frame);
3114                                 TALLOC_FREE(talloced);
3115                                 goto out;
3116                         }
3117
3118                         status = check_name(conn, smb_fname->base_name);
3119                         if (!NT_STATUS_IS_OK(status)) {
3120                                 TALLOC_FREE(dir_hnd);
3121                                 TALLOC_FREE(frame);
3122                                 TALLOC_FREE(talloced);
3123                                 goto out;
3124                         }
3125
3126                         status = do_unlink(conn, req, smb_fname, dirtype);
3127                         if (!NT_STATUS_IS_OK(status)) {
3128                                 TALLOC_FREE(dir_hnd);
3129                                 TALLOC_FREE(frame);
3130                                 TALLOC_FREE(talloced);
3131                                 goto out;
3132                         }
3133
3134                         count++;
3135                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3136                                  smb_fname->base_name));
3137
3138                         TALLOC_FREE(frame);
3139                         TALLOC_FREE(talloced);
3140                 }
3141                 TALLOC_FREE(dir_hnd);
3142         }
3143
3144         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3145                 status = map_nt_error_from_unix(errno);
3146         }
3147
3148  out:
3149         TALLOC_FREE(fname_dir);
3150         TALLOC_FREE(fname_mask);
3151         return status;
3152 }
3153
3154 /****************************************************************************
3155  Reply to a unlink
3156 ****************************************************************************/
3157
3158 void reply_unlink(struct smb_request *req)
3159 {
3160         connection_struct *conn = req->conn;
3161         char *name = NULL;
3162         struct smb_filename *smb_fname = NULL;
3163         uint32_t dirtype;
3164         NTSTATUS status;
3165         bool path_contains_wcard = False;
3166         uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3167                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
3168         TALLOC_CTX *ctx = talloc_tos();
3169
3170         START_PROFILE(SMBunlink);
3171
3172         if (req->wct < 1) {
3173                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3174                 goto out;
3175         }
3176
3177         dirtype = SVAL(req->vwv+0, 0);
3178
3179         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3180                                   STR_TERMINATE, &status,
3181                                   &path_contains_wcard);
3182         if (!NT_STATUS_IS_OK(status)) {
3183                 reply_nterror(req, status);
3184                 goto out;
3185         }
3186
3187         status = filename_convert(ctx, conn,
3188                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
3189                                   name,
3190                                   ucf_flags,
3191                                   &path_contains_wcard,
3192                                   &smb_fname);
3193         if (!NT_STATUS_IS_OK(status)) {
3194                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3195                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3196                                         ERRSRV, ERRbadpath);
3197                         goto out;
3198                 }
3199                 reply_nterror(req, status);
3200                 goto out;
3201         }
3202
3203         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3204
3205         status = unlink_internals(conn, req, dirtype, smb_fname,
3206                                   path_contains_wcard);
3207         if (!NT_STATUS_IS_OK(status)) {
3208                 if (open_was_deferred(req->xconn, req->mid)) {
3209                         /* We have re-scheduled this call. */
3210                         goto out;
3211                 }
3212                 reply_nterror(req, status);
3213                 goto out;
3214         }
3215
3216         reply_outbuf(req, 0, 0);
3217  out:
3218         TALLOC_FREE(smb_fname);
3219         END_PROFILE(SMBunlink);
3220         return;
3221 }
3222
3223 /****************************************************************************
3224  Fail for readbraw.
3225 ****************************************************************************/
3226
3227 static void fail_readraw(void)
3228 {
3229         const char *errstr = talloc_asprintf(talloc_tos(),
3230                         "FAIL ! reply_readbraw: socket write fail (%s)",
3231                         strerror(errno));
3232         if (!errstr) {
3233                 errstr = "";
3234         }
3235         exit_server_cleanly(errstr);
3236 }
3237
3238 /****************************************************************************
3239  Fake (read/write) sendfile. Returns -1 on read or write fail.
3240 ****************************************************************************/
3241
3242 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3243                       off_t startpos, size_t nread)
3244 {
3245         size_t bufsize;
3246         size_t tosend = nread;
3247         char *buf;
3248
3249         if (nread == 0) {
3250                 return 0;
3251         }
3252
3253         bufsize = MIN(nread, 65536);
3254
3255         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3256                 return -1;
3257         }
3258
3259         while (tosend > 0) {
3260                 ssize_t ret;
3261                 size_t cur_read;
3262
3263                 cur_read = MIN(tosend, bufsize);
3264                 ret = read_file(fsp,buf,startpos,cur_read);
3265                 if (ret == -1) {
3266                         SAFE_FREE(buf);
3267                         return -1;
3268                 }
3269
3270                 /* If we had a short read, fill with zeros. */
3271                 if (ret < cur_read) {
3272                         memset(buf + ret, '\0', cur_read - ret);
3273                 }
3274
3275                 ret = write_data(xconn->transport.sock, buf, cur_read);
3276                 if (ret != cur_read) {
3277                         int saved_errno = errno;
3278                         /*
3279                          * Try and give an error message saying what
3280                          * client failed.
3281                          */
3282                         DEBUG(0, ("write_data failed for client %s. "
3283                                   "Error %s\n",
3284                                   smbXsrv_connection_dbg(xconn),
3285                                   strerror(saved_errno)));
3286                         SAFE_FREE(buf);
3287                         errno = saved_errno;
3288                         return -1;
3289                 }
3290                 tosend -= cur_read;
3291                 startpos += cur_read;
3292         }
3293
3294         SAFE_FREE(buf);
3295         return (ssize_t)nread;
3296 }
3297
3298 /****************************************************************************
3299  Deal with the case of sendfile reading less bytes from the file than
3300  requested. Fill with zeros (all we can do). Returns 0 on success
3301 ****************************************************************************/
3302
3303 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3304                             files_struct *fsp,
3305                             ssize_t nread,
3306                             size_t headersize,
3307                             size_t smb_maxcnt)
3308 {
3309 #define SHORT_SEND_BUFSIZE 1024
3310         if (nread < headersize) {
3311                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3312                         "header for file %s (%s). Terminating\n",
3313                         fsp_str_dbg(fsp), strerror(errno)));
3314                 return -1;
3315         }
3316
3317         nread -= headersize;
3318
3319         if (nread < smb_maxcnt) {
3320                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3321                 if (!buf) {
3322                         DEBUG(0,("sendfile_short_send: malloc failed "
3323                                 "for file %s (%s). Terminating\n",
3324                                 fsp_str_dbg(fsp), strerror(errno)));
3325                         return -1;
3326                 }
3327
3328                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3329                         "with zeros !\n", fsp_str_dbg(fsp)));
3330
3331                 while (nread < smb_maxcnt) {
3332                         /*
3333                          * We asked for the real file size and told sendfile
3334                          * to not go beyond the end of the file. But it can
3335                          * happen that in between our fstat call and the
3336                          * sendfile call the file was truncated. This is very
3337                          * bad because we have already announced the larger
3338                          * number of bytes to the client.
3339                          *
3340                          * The best we can do now is to send 0-bytes, just as
3341                          * a read from a hole in a sparse file would do.
3342                          *
3343                          * This should happen rarely enough that I don't care
3344                          * about efficiency here :-)
3345                          */
3346                         size_t to_write;
3347                         ssize_t ret;
3348
3349                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3350                         ret = write_data(xconn->transport.sock, buf, to_write);
3351                         if (ret != to_write) {
3352                                 int saved_errno = errno;
3353                                 /*
3354                                  * Try and give an error message saying what
3355                                  * client failed.
3356                                  */
3357                                 DEBUG(0, ("write_data failed for client %s. "
3358                                           "Error %s\n",
3359                                           smbXsrv_connection_dbg(xconn),
3360                                           strerror(saved_errno)));
3361                                 errno = saved_errno;
3362                                 return -1;
3363                         }
3364                         nread += to_write;
3365                 }
3366                 SAFE_FREE(buf);
3367         }
3368
3369         return 0;
3370 }
3371
3372 /****************************************************************************
3373  Return a readbraw error (4 bytes of zero).
3374 ****************************************************************************/
3375
3376 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3377 {
3378         char header[4];
3379
3380         SIVAL(header,0,0);
3381
3382         smbd_lock_socket(xconn);
3383         if (write_data(xconn->transport.sock,header,4) != 4) {
3384                 int saved_errno = errno;
3385                 /*
3386                  * Try and give an error message saying what
3387                  * client failed.
3388                  */
3389                 DEBUG(0, ("write_data failed for client %s. "
3390                           "Error %s\n",
3391                           smbXsrv_connection_dbg(xconn),
3392                           strerror(saved_errno)));
3393                 errno = saved_errno;
3394
3395                 fail_readraw();
3396         }
3397         smbd_unlock_socket(xconn);
3398 }
3399
3400 /****************************************************************************
3401  Use sendfile in readbraw.
3402 ****************************************************************************/
3403
3404 static void send_file_readbraw(connection_struct *conn,
3405                                struct smb_request *req,
3406                                files_struct *fsp,
3407                                off_t startpos,
3408                                size_t nread,
3409                                ssize_t mincount)
3410 {
3411         struct smbXsrv_connection *xconn = req->xconn;
3412         char *outbuf = NULL;
3413         ssize_t ret=0;
3414
3415         /*
3416          * We can only use sendfile on a non-chained packet 
3417          * but we can use on a non-oplocked file. tridge proved this
3418          * on a train in Germany :-). JRA.
3419          * reply_readbraw has already checked the length.
3420          */
3421
3422         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3423             (fsp->wcp == NULL) &&
3424             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3425                 ssize_t sendfile_read = -1;
3426                 char header[4];
3427                 DATA_BLOB header_blob;
3428
3429                 _smb_setlen(header,nread);
3430                 header_blob = data_blob_const(header, 4);
3431
3432                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3433                                                  &header_blob, startpos,
3434                                                  nread);
3435                 if (sendfile_read == -1) {
3436                         /* Returning ENOSYS means no data at all was sent.
3437                          * Do this as a normal read. */
3438                         if (errno == ENOSYS) {
3439                                 goto normal_readbraw;
3440                         }
3441
3442                         /*
3443                          * Special hack for broken Linux with no working sendfile. If we
3444                          * return EINTR we sent the header but not the rest of the data.
3445                          * Fake this up by doing read/write calls.
3446                          */
3447                         if (errno == EINTR) {
3448                                 /* Ensure we don't do this again. */
3449                                 set_use_sendfile(SNUM(conn), False);
3450                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3451
3452                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3453                                         DEBUG(0,("send_file_readbraw: "
3454                                                  "fake_sendfile failed for "
3455                                                  "file %s (%s).\n",
3456                                                  fsp_str_dbg(fsp),
3457                                                  strerror(errno)));
3458                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3459                                 }
3460                                 return;
3461                         }
3462
3463                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3464                                  "file %s (%s). Terminating\n",
3465                                  fsp_str_dbg(fsp), strerror(errno)));
3466                         exit_server_cleanly("send_file_readbraw sendfile failed");
3467                 } else if (sendfile_read == 0) {
3468                         /*
3469                          * Some sendfile implementations return 0 to indicate
3470                          * that there was a short read, but nothing was
3471                          * actually written to the socket.  In this case,
3472                          * fallback to the normal read path so the header gets
3473                          * the correct byte count.
3474                          */
3475                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3476                                   "bytes falling back to the normal read: "
3477                                   "%s\n", fsp_str_dbg(fsp)));
3478                         goto normal_readbraw;
3479                 }
3480
3481                 /* Deal with possible short send. */
3482                 if (sendfile_read != 4+nread) {
3483                         ret = sendfile_short_send(xconn, fsp,
3484                                                   sendfile_read, 4, nread);
3485                         if (ret == -1) {
3486                                 fail_readraw();
3487                         }
3488                 }
3489                 return;
3490         }
3491
3492 normal_readbraw:
3493
3494         outbuf = talloc_array(NULL, char, nread+4);
3495         if (!outbuf) {
3496                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3497                         (unsigned)(nread+4)));
3498                 reply_readbraw_error(xconn);
3499                 return;
3500         }
3501
3502         if (nread > 0) {
3503                 ret = read_file(fsp,outbuf+4,startpos,nread);
3504 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3505                 if (ret < mincount)
3506                         ret = 0;
3507 #else
3508                 if (ret < nread)
3509                         ret = 0;
3510 #endif
3511         }
3512
3513         _smb_setlen(outbuf,ret);
3514         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3515                 int saved_errno = errno;
3516                 /*
3517                  * Try and give an error message saying what
3518                  * client failed.
3519                  */
3520                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3521                           smbXsrv_connection_dbg(xconn),
3522                           strerror(saved_errno)));
3523                 errno = saved_errno;
3524
3525                 fail_readraw();
3526         }
3527
3528         TALLOC_FREE(outbuf);
3529 }
3530
3531 /****************************************************************************
3532  Reply to a readbraw (core+ protocol).
3533 ****************************************************************************/
3534
3535 void reply_readbraw(struct smb_request *req)
3536 {
3537         connection_struct *conn = req->conn;
3538         struct smbXsrv_connection *xconn = req->xconn;
3539         ssize_t maxcount,mincount;
3540         size_t nread = 0;
3541         off_t startpos;
3542         files_struct *fsp;
3543         struct lock_struct lock;
3544         off_t size = 0;
3545
3546         START_PROFILE(SMBreadbraw);
3547
3548         if (srv_is_signing_active(xconn) || req->encrypted) {
3549                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3550                         "raw reads/writes are disallowed.");
3551         }
3552
3553         if (req->wct < 8) {
3554                 reply_readbraw_error(xconn);
3555                 END_PROFILE(SMBreadbraw);
3556                 return;
3557         }
3558
3559         if (xconn->smb1.echo_handler.trusted_fde) {
3560                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3561                          "'async smb echo handler = yes'\n"));
3562                 reply_readbraw_error(xconn);
3563                 END_PROFILE(SMBreadbraw);
3564                 return;
3565         }
3566
3567         /*
3568          * Special check if an oplock break has been issued
3569          * and the readraw request croses on the wire, we must
3570          * return a zero length response here.
3571          */
3572
3573         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3574
3575         /*
3576          * We have to do a check_fsp by hand here, as
3577          * we must always return 4 zero bytes on error,
3578          * not a NTSTATUS.
3579          */
3580
3581         if (!fsp || !conn || conn != fsp->conn ||
3582                         req->vuid != fsp->vuid ||
3583                         fsp->is_directory || fsp->fh->fd == -1) {
3584                 /*
3585                  * fsp could be NULL here so use the value from the packet. JRA.
3586                  */
3587                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3588                         "- cache prime?\n",
3589                         (int)SVAL(req->vwv+0, 0)));
3590                 reply_readbraw_error(xconn);
3591                 END_PROFILE(SMBreadbraw);
3592                 return;
3593         }
3594
3595         /* Do a "by hand" version of CHECK_READ. */
3596         if (!(fsp->can_read ||
3597                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3598                                 (fsp->access_mask & FILE_EXECUTE)))) {
3599                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3600                                 (int)SVAL(req->vwv+0, 0)));
3601                 reply_readbraw_error(xconn);
3602                 END_PROFILE(SMBreadbraw);
3603                 return;
3604         }
3605
3606         flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3607
3608         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3609         if(req->wct == 10) {
3610                 /*
3611                  * This is a large offset (64 bit) read.
3612                  */
3613
3614                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3615
3616                 if(startpos < 0) {
3617                         DEBUG(0,("reply_readbraw: negative 64 bit "
3618                                 "readraw offset (%.0f) !\n",
3619                                 (double)startpos ));
3620                         reply_readbraw_error(xconn);
3621                         END_PROFILE(SMBreadbraw);
3622                         return;
3623                 }
3624         }
3625
3626         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3627         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3628
3629         /* ensure we don't overrun the packet size */
3630         maxcount = MIN(65535,maxcount);
3631
3632         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3633             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3634             &lock);
3635
3636         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3637                 reply_readbraw_error(xconn);
3638                 END_PROFILE(SMBreadbraw);
3639                 return;
3640         }
3641
3642         if (fsp_stat(fsp) == 0) {
3643                 size = fsp->fsp_name->st.st_ex_size;
3644         }
3645
3646         if (startpos >= size) {
3647                 nread = 0;
3648         } else {
3649                 nread = MIN(maxcount,(size - startpos));
3650         }
3651
3652 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3653         if (nread < mincount)
3654                 nread = 0;
3655 #endif
3656
3657         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3658                 "min=%lu nread=%lu\n",
3659                 fsp_fnum_dbg(fsp), (double)startpos,
3660                 (unsigned long)maxcount,
3661                 (unsigned long)mincount,
3662                 (unsigned long)nread ) );
3663
3664         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3665
3666         DEBUG(5,("reply_readbraw finished\n"));
3667
3668         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3669
3670         END_PROFILE(SMBreadbraw);
3671         return;
3672 }
3673
3674 #undef DBGC_CLASS
3675 #define DBGC_CLASS DBGC_LOCKING
3676
3677 /****************************************************************************
3678  Reply to a lockread (core+ protocol).
3679 ****************************************************************************/
3680
3681 void reply_lockread(struct smb_request *req)
3682 {
3683         connection_struct *conn = req->conn;
3684         ssize_t nread = -1;
3685         char *data;
3686         off_t startpos;
3687         size_t numtoread;
3688         size_t maxtoread;
3689         NTSTATUS status;
3690         files_struct *fsp;
3691         struct byte_range_lock *br_lck = NULL;
3692         char *p = NULL;
3693         struct smbXsrv_connection *xconn = req->xconn;
3694
3695         START_PROFILE(SMBlockread);
3696
3697         if (req->wct < 5) {
3698                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3699                 END_PROFILE(SMBlockread);
3700                 return;
3701         }
3702
3703         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3704
3705         if (!check_fsp(conn, req, fsp)) {
3706                 END_PROFILE(SMBlockread);
3707                 return;
3708         }
3709
3710         if (!CHECK_READ(fsp,req)) {
3711                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3712                 END_PROFILE(SMBlockread);
3713                 return;
3714         }
3715
3716         numtoread = SVAL(req->vwv+1, 0);
3717         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3718
3719         /*
3720          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3721          * protocol request that predates the read/write lock concept. 
3722          * Thus instead of asking for a read lock here we need to ask
3723          * for a write lock. JRA.
3724          * Note that the requested lock size is unaffected by max_send.
3725          */
3726
3727         br_lck = do_lock(req->sconn->msg_ctx,
3728                         fsp,
3729                         (uint64_t)req->smbpid,
3730                         (uint64_t)numtoread,
3731                         (uint64_t)startpos,
3732                         WRITE_LOCK,
3733                         WINDOWS_LOCK,
3734                         False, /* Non-blocking lock. */
3735                         &status,
3736                         NULL);
3737         TALLOC_FREE(br_lck);
3738
3739         if (NT_STATUS_V(status)) {
3740                 reply_nterror(req, status);
3741                 END_PROFILE(SMBlockread);
3742                 return;
3743         }
3744
3745         /*
3746          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3747          */
3748         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3749
3750         if (numtoread > maxtoread) {
3751                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3752 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3753                         (unsigned int)numtoread, (unsigned int)maxtoread,
3754                         (unsigned int)xconn->smb1.sessions.max_send));
3755                 numtoread = maxtoread;
3756         }
3757
3758         reply_outbuf(req, 5, numtoread + 3);
3759
3760         data = smb_buf(req->outbuf) + 3;
3761
3762         nread = read_file(fsp,data,startpos,numtoread);
3763
3764         if (nread < 0) {
3765                 reply_nterror(req, map_nt_error_from_unix(errno));
3766                 END_PROFILE(SMBlockread);
3767                 return;
3768         }
3769
3770         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3771
3772         SSVAL(req->outbuf,smb_vwv0,nread);
3773         SSVAL(req->outbuf,smb_vwv5,nread+3);
3774         p = smb_buf(req->outbuf);
3775         SCVAL(p,0,0); /* pad byte. */
3776         SSVAL(p,1,nread);
3777
3778         DEBUG(3,("lockread %s num=%d nread=%d\n",
3779                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3780
3781         END_PROFILE(SMBlockread);
3782         return;
3783 }
3784
3785 #undef DBGC_CLASS
3786 #define DBGC_CLASS DBGC_ALL
3787
3788 /****************************************************************************
3789  Reply to a read.
3790 ****************************************************************************/
3791
3792 void reply_read(struct smb_request *req)
3793 {
3794         connection_struct *conn = req->conn;
3795         size_t numtoread;
3796         size_t maxtoread;
3797         ssize_t nread = 0;
3798         char *data;
3799         off_t startpos;
3800         files_struct *fsp;
3801         struct lock_struct lock;
3802         struct smbXsrv_connection *xconn = req->xconn;
3803
3804         START_PROFILE(SMBread);
3805
3806         if (req->wct < 3) {
3807                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3808                 END_PROFILE(SMBread);
3809                 return;
3810         }
3811
3812         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3813
3814         if (!check_fsp(conn, req, fsp)) {
3815                 END_PROFILE(SMBread);
3816                 return;
3817         }
3818
3819         if (!CHECK_READ(fsp,req)) {
3820                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3821                 END_PROFILE(SMBread);
3822                 return;
3823         }
3824
3825         numtoread = SVAL(req->vwv+1, 0);
3826         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3827
3828         /*
3829          * The requested read size cannot be greater than max_send. JRA.
3830          */
3831         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3832
3833         if (numtoread > maxtoread) {
3834                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3835 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3836                         (unsigned int)numtoread, (unsigned int)maxtoread,
3837                         (unsigned int)xconn->smb1.sessions.max_send));
3838                 numtoread = maxtoread;
3839         }
3840
3841         reply_outbuf(req, 5, numtoread+3);
3842
3843         data = smb_buf(req->outbuf) + 3;
3844
3845         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3846             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3847             &lock);
3848
3849         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3850                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3851                 END_PROFILE(SMBread);
3852                 return;
3853         }
3854
3855         if (numtoread > 0)
3856                 nread = read_file(fsp,data,startpos,numtoread);
3857
3858         if (nread < 0) {
3859                 reply_nterror(req, map_nt_error_from_unix(errno));
3860                 goto strict_unlock;
3861         }
3862
3863         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3864
3865         SSVAL(req->outbuf,smb_vwv0,nread);
3866         SSVAL(req->outbuf,smb_vwv5,nread+3);
3867         SCVAL(smb_buf(req->outbuf),0,1);
3868         SSVAL(smb_buf(req->outbuf),1,nread);
3869
3870         DEBUG(3, ("read %s num=%d nread=%d\n",
3871                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3872
3873 strict_unlock:
3874         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3875
3876         END_PROFILE(SMBread);
3877         return;
3878 }
3879
3880 /****************************************************************************
3881  Setup readX header.
3882 ****************************************************************************/
3883
3884 static int setup_readX_header(struct smb_request *req, char *outbuf,
3885                               size_t smb_maxcnt)
3886 {
3887         int outsize;
3888
3889         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3890                                   False);
3891
3892         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3893
3894         SCVAL(outbuf,smb_vwv0,0xFF);
3895         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3896         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3897         SSVAL(outbuf,smb_vwv6,
3898               (smb_wct - 4)     /* offset from smb header to wct */
3899               + 1               /* the wct field */
3900               + 12 * sizeof(uint16_t) /* vwv */
3901               + 2               /* the buflen field */
3902               + 1);             /* padding byte */
3903         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3904         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3905         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3906         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3907         _smb_setlen_large(outbuf,
3908                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3909         return outsize;
3910 }
3911
3912 /****************************************************************************
3913  Reply to a read and X - possibly using sendfile.
3914 ****************************************************************************/
3915
3916 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3917                             files_struct *fsp, off_t startpos,
3918                             size_t smb_maxcnt)
3919 {
3920         struct smbXsrv_connection *xconn = req->xconn;
3921         ssize_t nread = -1;
3922         struct lock_struct lock;
3923         int saved_errno = 0;
3924
3925         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3926             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3927             &lock);
3928
3929         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3930                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3931                 return;
3932         }
3933
3934         /*
3935          * We can only use sendfile on a non-chained packet
3936          * but we can use on a non-oplocked file. tridge proved this
3937          * on a train in Germany :-). JRA.
3938          */
3939
3940         if (!req_is_in_chain(req) &&
3941             !req->encrypted &&
3942             (fsp->base_fsp == NULL) &&
3943             (fsp->wcp == NULL) &&
3944             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3945                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3946                 DATA_BLOB header;
3947
3948                 if(fsp_stat(fsp) == -1) {
3949                         reply_nterror(req, map_nt_error_from_unix(errno));
3950                         goto strict_unlock;
3951                 }
3952
3953                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3954                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3955                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3956                         /*
3957                          * We already know that we would do a short read, so don't
3958                          * try the sendfile() path.
3959                          */
3960                         goto nosendfile_read;
3961                 }
3962
3963                 /*
3964                  * Set up the packet header before send. We
3965                  * assume here the sendfile will work (get the
3966                  * correct amount of data).
3967                  */
3968
3969                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3970
3971                 construct_reply_common_req(req, (char *)headerbuf);
3972                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3973
3974                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3975                                          startpos, smb_maxcnt);
3976                 if (nread == -1) {
3977                         saved_errno = errno;
3978
3979                         /* Returning ENOSYS means no data at all was sent.
3980                            Do this as a normal read. */
3981                         if (errno == ENOSYS) {
3982                                 goto normal_read;
3983                         }
3984
3985                         /*
3986                          * Special hack for broken Linux with no working sendfile. If we
3987                          * return EINTR we sent the header but not the rest of the data.
3988                          * Fake this up by doing read/write calls.
3989                          */
3990
3991                         if (errno == EINTR) {
3992                                 /* Ensure we don't do this again. */
3993                                 set_use_sendfile(SNUM(conn), False);
3994                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3995                                 nread = fake_sendfile(xconn, fsp, startpos,
3996                                                       smb_maxcnt);
3997                                 if (nread == -1) {
3998                                         saved_errno = errno;
3999                                         DEBUG(0,("send_file_readX: "
4000                                                  "fake_sendfile failed for "
4001                                                  "file %s (%s) for client %s. "
4002                                                  "Terminating\n",
4003                                                  fsp_str_dbg(fsp),
4004                                                  smbXsrv_connection_dbg(xconn),
4005                                                  strerror(saved_errno)));
4006                                         errno = saved_errno;
4007                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4008                                 }
4009                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4010                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4011                                 /* No outbuf here means successful sendfile. */
4012                                 goto strict_unlock;
4013                         }
4014
4015                         DEBUG(0,("send_file_readX: sendfile failed for file "
4016                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4017                                  strerror(errno)));
4018                         exit_server_cleanly("send_file_readX sendfile failed");
4019                 } else if (nread == 0) {
4020                         /*
4021                          * Some sendfile implementations return 0 to indicate
4022                          * that there was a short read, but nothing was
4023                          * actually written to the socket.  In this case,
4024                          * fallback to the normal read path so the header gets
4025                          * the correct byte count.
4026                          */
4027                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4028                                   "falling back to the normal read: %s\n",
4029                                   fsp_str_dbg(fsp)));
4030                         goto normal_read;
4031                 }
4032
4033                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4034                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4035
4036                 /* Deal with possible short send. */
4037                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4038                         ssize_t ret;
4039
4040                         ret = sendfile_short_send(xconn, fsp, nread,
4041                                                   sizeof(headerbuf), smb_maxcnt);
4042                         if (ret == -1) {
4043                                 const char *r;
4044                                 r = "send_file_readX: sendfile_short_send failed";
4045                                 DEBUG(0,("%s for file %s (%s).\n",
4046                                          r, fsp_str_dbg(fsp), strerror(errno)));
4047                                 exit_server_cleanly(r);
4048                         }
4049                 }
4050                 /* No outbuf here means successful sendfile. */
4051                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4052                 SMB_PERFCOUNT_END(&req->pcd);
4053                 goto strict_unlock;
4054         }
4055
4056 normal_read:
4057
4058         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4059                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4060                 ssize_t ret;
4061
4062                 construct_reply_common_req(req, (char *)headerbuf);
4063                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
4064
4065                 /* Send out the header. */
4066                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4067                                  sizeof(headerbuf));
4068                 if (ret != sizeof(headerbuf)) {
4069                         saved_errno = errno;
4070                         /*
4071                          * Try and give an error message saying what
4072                          * client failed.
4073                          */
4074                         DEBUG(0,("send_file_readX: write_data failed for file "
4075                                  "%s (%s) for client %s. Terminating\n",
4076                                  fsp_str_dbg(fsp),
4077                                  smbXsrv_connection_dbg(xconn),
4078                                  strerror(saved_errno)));
4079                         errno = saved_errno;
4080                         exit_server_cleanly("send_file_readX sendfile failed");
4081                 }
4082                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4083                 if (nread == -1) {
4084                         saved_errno = errno;
4085                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4086                                  "%s (%s) for client %s. Terminating\n",
4087                                  fsp_str_dbg(fsp),
4088                                  smbXsrv_connection_dbg(xconn),
4089                                  strerror(saved_errno)));
4090                         errno = saved_errno;
4091                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
4092                 }
4093                 goto strict_unlock;
4094         }
4095
4096 nosendfile_read:
4097
4098         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4099         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4100         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4101
4102         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4103                           startpos, smb_maxcnt);
4104         saved_errno = errno;
4105
4106         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4107
4108         if (nread < 0) {
4109                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4110                 return;
4111         }
4112
4113         setup_readX_header(req, (char *)req->outbuf, nread);
4114
4115         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4116                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4117         return;
4118
4119  strict_unlock:
4120         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4121         TALLOC_FREE(req->outbuf);
4122         return;
4123 }
4124
4125 /****************************************************************************
4126  Work out how much space we have for a read return.
4127 ****************************************************************************/
4128
4129 static size_t calc_max_read_pdu(const struct smb_request *req)
4130 {
4131         struct smbXsrv_connection *xconn = req->xconn;
4132
4133         if (xconn->protocol < PROTOCOL_NT1) {
4134                 return xconn->smb1.sessions.max_send;
4135         }
4136
4137         if (!lp_large_readwrite()) {
4138                 return xconn->smb1.sessions.max_send;
4139         }
4140
4141         if (req_is_in_chain(req)) {
4142                 return xconn->smb1.sessions.max_send;
4143         }
4144
4145         if (req->encrypted) {
4146                 /*
4147                  * Don't take encrypted traffic up to the
4148                  * limit. There are padding considerations
4149                  * that make that tricky.
4150                  */
4151                 return xconn->smb1.sessions.max_send;
4152         }
4153
4154         if (srv_is_signing_active(xconn)) {
4155                 return 0x1FFFF;
4156         }
4157
4158         if (!lp_unix_extensions()) {
4159                 return 0x1FFFF;
4160         }
4161
4162         /*
4163          * We can do ultra-large POSIX reads.
4164          */
4165         return 0xFFFFFF;
4166 }
4167
4168 /****************************************************************************
4169  Calculate how big a read can be. Copes with all clients. It's always
4170  safe to return a short read - Windows does this.
4171 ****************************************************************************/
4172
4173 static size_t calc_read_size(const struct smb_request *req,
4174                              size_t upper_size,
4175                              size_t lower_size)
4176 {
4177         struct smbXsrv_connection *xconn = req->xconn;
4178         size_t max_pdu = calc_max_read_pdu(req);
4179         size_t total_size = 0;
4180         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4181         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4182
4183         /*
4184          * Windows explicitly ignores upper size of 0xFFFF.
4185          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4186          * We must do the same as these will never fit even in
4187          * an extended size NetBIOS packet.
4188          */
4189         if (upper_size == 0xFFFF) {
4190                 upper_size = 0;
4191         }
4192
4193         if (xconn->protocol < PROTOCOL_NT1) {
4194                 upper_size = 0;
4195         }
4196
4197         total_size = ((upper_size<<16) | lower_size);
4198
4199         /*
4200          * LARGE_READX test shows it's always safe to return
4201          * a short read. Windows does so.
4202          */
4203         return MIN(total_size, max_len);
4204 }
4205
4206 /****************************************************************************
4207  Reply to a read and X.
4208 ****************************************************************************/
4209
4210 void reply_read_and_X(struct smb_request *req)
4211 {
4212         connection_struct *conn = req->conn;
4213         files_struct *fsp;
4214         off_t startpos;
4215         size_t smb_maxcnt;
4216         size_t upper_size;
4217         bool big_readX = False;
4218 #if 0
4219         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4220 #endif
4221
4222         START_PROFILE(SMBreadX);
4223
4224         if ((req->wct != 10) && (req->wct != 12)) {
4225                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4226                 return;
4227         }
4228
4229         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4230         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4231         smb_maxcnt = SVAL(req->vwv+5, 0);
4232
4233         /* If it's an IPC, pass off the pipe handler. */
4234         if (IS_IPC(conn)) {
4235                 reply_pipe_read_and_X(req);
4236                 END_PROFILE(SMBreadX);
4237                 return;
4238         }
4239
4240         if (!check_fsp(conn, req, fsp)) {
4241                 END_PROFILE(SMBreadX);
4242                 return;
4243         }
4244
4245         if (!CHECK_READ(fsp,req)) {
4246                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4247                 END_PROFILE(SMBreadX);
4248                 return;
4249         }
4250
4251         upper_size = SVAL(req->vwv+7, 0);
4252         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4253         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4254                 /*
4255                  * This is a heuristic to avoid keeping large
4256                  * outgoing buffers around over long-lived aio
4257                  * requests.
4258                  */
4259                 big_readX = True;
4260         }
4261
4262         if (req->wct == 12) {
4263                 /*
4264                  * This is a large offset (64 bit) read.
4265                  */
4266                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4267
4268         }
4269
4270         if (!big_readX) {
4271                 NTSTATUS status = schedule_aio_read_and_X(conn,
4272                                         req,
4273                                         fsp,
4274                                         startpos,
4275                                         smb_maxcnt);
4276                 if (NT_STATUS_IS_OK(status)) {
4277                         /* Read scheduled - we're done. */
4278                         goto out;
4279                 }
4280                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4281                         /* Real error - report to client. */
4282                         END_PROFILE(SMBreadX);
4283                         reply_nterror(req, status);
4284                         return;
4285                 }
4286                 /* NT_STATUS_RETRY - fall back to sync read. */
4287         }
4288
4289         smbd_lock_socket(req->xconn);
4290         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4291         smbd_unlock_socket(req->xconn);
4292
4293  out:
4294         END_PROFILE(SMBreadX);
4295         return;
4296 }
4297
4298 /****************************************************************************
4299  Error replies to writebraw must have smb_wct == 1. Fix this up.
4300 ****************************************************************************/
4301
4302 void error_to_writebrawerr(struct smb_request *req)
4303 {
4304         uint8_t *old_outbuf = req->outbuf;
4305
4306         reply_outbuf(req, 1, 0);
4307
4308         memcpy(req->outbuf, old_outbuf, smb_size);
4309         TALLOC_FREE(old_outbuf);
4310 }
4311
4312 /****************************************************************************
4313  Read 4 bytes of a smb packet and return the smb length of the packet.
4314  Store the result in the buffer. This version of the function will
4315  never return a session keepalive (length of zero).
4316  Timeout is in milliseconds.
4317 ****************************************************************************/
4318
4319 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4320                                 size_t *len)
4321 {
4322         uint8_t msgtype = NBSSkeepalive;
4323
4324         while (msgtype == NBSSkeepalive) {
4325                 NTSTATUS status;
4326
4327                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4328                                                           len);
4329                 if (!NT_STATUS_IS_OK(status)) {
4330                         char addr[INET6_ADDRSTRLEN];
4331                         /* Try and give an error message
4332                          * saying what client failed. */
4333                         DEBUG(0, ("read_fd_with_timeout failed for "
4334                                   "client %s read error = %s.\n",
4335                                   get_peer_addr(fd,addr,sizeof(addr)),
4336                                   nt_errstr(status)));
4337                         return status;
4338                 }
4339
4340                 msgtype = CVAL(inbuf, 0);
4341         }
4342
4343         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4344                   (unsigned long)len));
4345
4346         return NT_STATUS_OK;
4347 }
4348
4349 /****************************************************************************
4350  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4351 ****************************************************************************/
4352
4353 void reply_writebraw(struct smb_request *req)
4354 {
4355         connection_struct *conn = req->conn;
4356         struct smbXsrv_connection *xconn = req->xconn;
4357         char *buf = NULL;
4358         ssize_t nwritten=0;
4359         ssize_t total_written=0;
4360         size_t numtowrite=0;
4361         size_t tcount;
4362         off_t startpos;
4363         const char *data=NULL;
4364         bool write_through;
4365         files_struct *fsp;
4366         struct lock_struct lock;
4367         NTSTATUS status;
4368
4369         START_PROFILE(SMBwritebraw);
4370
4371         /*
4372          * If we ever reply with an error, it must have the SMB command
4373          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4374          * we're finished.
4375          */
4376         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4377
4378         if (srv_is_signing_active(xconn)) {
4379                 END_PROFILE(SMBwritebraw);
4380                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4381                                 "raw reads/writes are disallowed.");
4382         }
4383
4384         if (req->wct < 12) {
4385                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4386                 error_to_writebrawerr(req);
4387                 END_PROFILE(SMBwritebraw);
4388                 return;
4389         }
4390
4391         if (xconn->smb1.echo_handler.trusted_fde) {
4392                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4393                          "'async smb echo handler = yes'\n"));
4394                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4395                 error_to_writebrawerr(req);
4396                 END_PROFILE(SMBwritebraw);
4397                 return;
4398         }
4399
4400         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4401         if (!check_fsp(conn, req, fsp)) {
4402                 error_to_writebrawerr(req);
4403                 END_PROFILE(SMBwritebraw);
4404                 return;
4405         }
4406
4407         if (!CHECK_WRITE(fsp)) {
4408                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4409                 error_to_writebrawerr(req);
4410                 END_PROFILE(SMBwritebraw);
4411                 return;
4412         }
4413
4414         tcount = IVAL(req->vwv+1, 0);
4415         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4416         write_through = BITSETW(req->vwv+7,0);
4417
4418         /* We have to deal with slightly different formats depending
4419                 on whether we are using the core+ or lanman1.0 protocol */
4420
4421         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4422                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4423                 data = smb_buf_const(req->inbuf);
4424         } else {
4425                 numtowrite = SVAL(req->vwv+10, 0);
4426                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4427         }
4428
4429         /* Ensure we don't write bytes past the end of this packet. */
4430         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4431                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4432                 error_to_writebrawerr(req);
4433                 END_PROFILE(SMBwritebraw);
4434                 return;
4435         }
4436
4437         if (!fsp->print_file) {
4438                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4439                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4440                     &lock);
4441
4442                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4443                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4444                         error_to_writebrawerr(req);
4445                         END_PROFILE(SMBwritebraw);
4446                         return;
4447                 }
4448         }
4449
4450         if (numtowrite>0) {
4451                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4452         }
4453
4454         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4455                         "wrote=%d sync=%d\n",
4456                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4457                 (int)nwritten, (int)write_through));
4458
4459         if (nwritten < (ssize_t)numtowrite)  {
4460                 reply_nterror(req, NT_STATUS_DISK_FULL);
4461                 error_to_writebrawerr(req);
4462                 goto strict_unlock;
4463         }
4464
4465         total_written = nwritten;
4466
4467         /* Allocate a buffer of 64k + length. */
4468         buf = talloc_array(NULL, char, 65540);
4469         if (!buf) {
4470                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4471                 error_to_writebrawerr(req);
4472                 goto strict_unlock;
4473         }
4474
4475         /* Return a SMBwritebraw message to the redirector to tell
4476          * it to send more bytes */
4477
4478         memcpy(buf, req->inbuf, smb_size);
4479         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4480         SCVAL(buf,smb_com,SMBwritebraw);
4481         SSVALS(buf,smb_vwv0,0xFFFF);
4482         show_msg(buf);
4483         if (!srv_send_smb(req->xconn,
4484                           buf,
4485                           false, 0, /* no signing */
4486                           IS_CONN_ENCRYPTED(conn),
4487                           &req->pcd)) {
4488                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4489                         "failed.");
4490         }
4491
4492         /* Now read the raw data into the buffer and write it */
4493         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4494                                  &numtowrite);
4495         if (!NT_STATUS_IS_OK(status)) {
4496                 exit_server_cleanly("secondary writebraw failed");
4497         }
4498
4499         /* Set up outbuf to return the correct size */
4500         reply_outbuf(req, 1, 0);
4501
4502         if (numtowrite != 0) {
4503
4504                 if (numtowrite > 0xFFFF) {
4505                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4506                                 "raw requested (%u). Terminating\n",
4507                                 (unsigned int)numtowrite ));
4508                         exit_server_cleanly("secondary writebraw failed");
4509                 }
4510
4511                 if (tcount > nwritten+numtowrite) {
4512                         DEBUG(3,("reply_writebraw: Client overestimated the "
4513                                 "write %d %d %d\n",
4514                                 (int)tcount,(int)nwritten,(int)numtowrite));
4515                 }
4516
4517                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4518                                             numtowrite);
4519
4520                 if (!NT_STATUS_IS_OK(status)) {
4521                         /* Try and give an error message
4522                          * saying what client failed. */
4523                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4524                                   "raw read failed (%s) for client %s. "
4525                                   "Terminating\n", nt_errstr(status),
4526                                   smbXsrv_connection_dbg(xconn)));
4527                         exit_server_cleanly("secondary writebraw failed");
4528                 }
4529
4530                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4531                 if (nwritten == -1) {
4532                         TALLOC_FREE(buf);
4533                         reply_nterror(req, map_nt_error_from_unix(errno));
4534                         error_to_writebrawerr(req);
4535                         goto strict_unlock;
4536                 }
4537
4538                 if (nwritten < (ssize_t)numtowrite) {
4539                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4540                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4541                 }
4542
4543                 if (nwritten > 0) {
4544                         total_written += nwritten;
4545                 }
4546         }
4547
4548         TALLOC_FREE(buf);
4549         SSVAL(req->outbuf,smb_vwv0,total_written);
4550
4551         status = sync_file(conn, fsp, write_through);
4552         if (!NT_STATUS_IS_OK(status)) {
4553                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4554                          fsp_str_dbg(fsp), nt_errstr(status)));
4555                 reply_nterror(req, status);
4556                 error_to_writebrawerr(req);
4557                 goto strict_unlock;
4558         }
4559
4560         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4561                 "wrote=%d\n",
4562                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4563                 (int)total_written));
4564
4565         if (!fsp->print_file) {
4566                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4567         }
4568
4569         /* We won't return a status if write through is not selected - this
4570          * follows what WfWg does */
4571         END_PROFILE(SMBwritebraw);
4572
4573         if (!write_through && total_written==tcount) {
4574
4575 #if RABBIT_PELLET_FIX
4576                 /*
4577                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4578                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4579                  * JRA.
4580                  */
4581                 if (!send_keepalive(xconn->transport.sock)) {
4582                         exit_server_cleanly("reply_writebraw: send of "
4583                                 "keepalive failed");
4584                 }
4585 #endif
4586                 TALLOC_FREE(req->outbuf);
4587         }
4588         return;
4589
4590 strict_unlock:
4591         if (!fsp->print_file) {
4592                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4593         }
4594
4595         END_PROFILE(SMBwritebraw);
4596         return;
4597 }
4598
4599 #undef DBGC_CLASS
4600 #define DBGC_CLASS DBGC_LOCKING
4601
4602 /****************************************************************************
4603  Reply to a writeunlock (core+).
4604 ****************************************************************************/
4605
4606 void reply_writeunlock(struct smb_request *req)
4607 {
4608         connection_struct *conn = req->conn;
4609         ssize_t nwritten = -1;
4610         size_t numtowrite;
4611         off_t startpos;
4612         const char *data;
4613         NTSTATUS status = NT_STATUS_OK;
4614         files_struct *fsp;
4615         struct lock_struct lock;
4616         int saved_errno = 0;
4617
4618         START_PROFILE(SMBwriteunlock);
4619
4620         if (req->wct < 5) {
4621                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4622                 END_PROFILE(SMBwriteunlock);
4623                 return;
4624         }
4625
4626         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4627
4628         if (!check_fsp(conn, req, fsp)) {
4629                 END_PROFILE(SMBwriteunlock);
4630                 return;
4631         }
4632
4633         if (!CHECK_WRITE(fsp)) {
4634                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4635                 END_PROFILE(SMBwriteunlock);
4636                 return;
4637         }
4638
4639         numtowrite = SVAL(req->vwv+1, 0);
4640         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4641         data = (const char *)req->buf + 3;
4642
4643         if (!fsp->print_file && numtowrite > 0) {
4644                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4645                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4646                     &lock);
4647
4648                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4649                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4650                         END_PROFILE(SMBwriteunlock);
4651                         return;
4652                 }
4653         }
4654
4655         /* The special X/Open SMB protocol handling of
4656            zero length writes is *NOT* done for
4657            this call */
4658         if(numtowrite == 0) {
4659                 nwritten = 0;
4660         } else {
4661                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4662                 saved_errno = errno;
4663         }
4664
4665         status = sync_file(conn, fsp, False /* write through */);
4666         if (!NT_STATUS_IS_OK(status)) {
4667                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4668                          fsp_str_dbg(fsp), nt_errstr(status)));
4669                 reply_nterror(req, status);
4670                 goto strict_unlock;
4671         }
4672
4673         if(nwritten < 0) {
4674                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4675                 goto strict_unlock;
4676         }
4677
4678         if((nwritten < numtowrite) && (numtowrite != 0)) {
4679                 reply_nterror(req, NT_STATUS_DISK_FULL);
4680                 goto strict_unlock;
4681         }
4682
4683         if (numtowrite && !fsp->print_file) {
4684                 status = do_unlock(req->sconn->msg_ctx,
4685                                 fsp,
4686                                 (uint64_t)req->smbpid,
4687                                 (uint64_t)numtowrite, 
4688                                 (uint64_t)startpos,
4689                                 WINDOWS_LOCK);
4690
4691                 if (NT_STATUS_V(status)) {
4692                         reply_nterror(req, status);
4693                         goto strict_unlock;
4694                 }
4695         }
4696
4697         reply_outbuf(req, 1, 0);
4698
4699         SSVAL(req->outbuf,smb_vwv0,nwritten);
4700
4701         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4702                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4703
4704 strict_unlock:
4705         if (numtowrite && !fsp->print_file) {
4706                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4707         }
4708
4709         END_PROFILE(SMBwriteunlock);
4710         return;
4711 }
4712
4713 #undef DBGC_CLASS
4714 #define DBGC_CLASS DBGC_ALL
4715
4716 /****************************************************************************
4717  Reply to a write.
4718 ****************************************************************************/
4719
4720 void reply_write(struct smb_request *req)
4721 {
4722         connection_struct *conn = req->conn;
4723         size_t numtowrite;
4724         ssize_t nwritten = -1;
4725         off_t startpos;
4726         const char *data;
4727         files_struct *fsp;
4728         struct lock_struct lock;
4729         NTSTATUS status;
4730         int saved_errno = 0;
4731
4732         START_PROFILE(SMBwrite);
4733
4734         if (req->wct < 5) {
4735                 END_PROFILE(SMBwrite);
4736                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4737                 return;
4738         }
4739
4740         /* If it's an IPC, pass off the pipe handler. */
4741         if (IS_IPC(conn)) {
4742                 reply_pipe_write(req);
4743                 END_PROFILE(SMBwrite);
4744                 return;
4745         }
4746
4747         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4748
4749         if (!check_fsp(conn, req, fsp)) {
4750                 END_PROFILE(SMBwrite);
4751                 return;
4752         }
4753
4754         if (!CHECK_WRITE(fsp)) {
4755                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4756                 END_PROFILE(SMBwrite);
4757                 return;
4758         }
4759
4760         numtowrite = SVAL(req->vwv+1, 0);
4761         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4762         data = (const char *)req->buf + 3;
4763
4764         if (!fsp->print_file) {
4765                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4766                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4767                         &lock);
4768
4769                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4770                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4771                         END_PROFILE(SMBwrite);
4772                         return;
4773                 }
4774         }
4775
4776         /*
4777          * X/Open SMB protocol says that if smb_vwv1 is
4778          * zero then the file size should be extended or
4779          * truncated to the size given in smb_vwv[2-3].
4780          */
4781
4782         if(numtowrite == 0) {
4783                 /*
4784                  * This is actually an allocate call, and set EOF. JRA.
4785                  */
4786                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4787                 if (nwritten < 0) {
4788                         reply_nterror(req, NT_STATUS_DISK_FULL);
4789                         goto strict_unlock;
4790                 }
4791                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4792                 if (nwritten < 0) {
4793                         reply_nterror(req, NT_STATUS_DISK_FULL);
4794                         goto strict_unlock;
4795                 }
4796                 trigger_write_time_update_immediate(fsp);
4797         } else {
4798                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4799         }
4800
4801         status = sync_file(conn, fsp, False);
4802         if (!NT_STATUS_IS_OK(status)) {
4803                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4804                          fsp_str_dbg(fsp), nt_errstr(status)));
4805                 reply_nterror(req, status);
4806                 goto strict_unlock;
4807         }
4808
4809         if(nwritten < 0) {
4810                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4811                 goto strict_unlock;
4812         }
4813
4814         if((nwritten == 0) && (numtowrite != 0)) {
4815                 reply_nterror(req, NT_STATUS_DISK_FULL);
4816                 goto strict_unlock;
4817         }
4818
4819         reply_outbuf(req, 1, 0);
4820
4821         SSVAL(req->outbuf,smb_vwv0,nwritten);
4822
4823         if (nwritten < (ssize_t)numtowrite) {
4824                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4825                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4826         }
4827
4828         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4829
4830 strict_unlock:
4831         if (!fsp->print_file) {
4832                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4833         }
4834
4835         END_PROFILE(SMBwrite);
4836         return;
4837 }
4838
4839 /****************************************************************************
4840  Ensure a buffer is a valid writeX for recvfile purposes.
4841 ****************************************************************************/
4842
4843 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4844                                                 (2*14) + /* word count (including bcc) */ \
4845                                                 1 /* pad byte */)
4846
4847 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4848                             const uint8_t *inbuf)
4849 {
4850         size_t numtowrite;
4851         unsigned int doff = 0;
4852         size_t len = smb_len_large(inbuf);
4853         uint16_t fnum;
4854         struct smbXsrv_open *op = NULL;
4855         struct files_struct *fsp = NULL;
4856         NTSTATUS status;
4857
4858         if (is_encrypted_packet(inbuf)) {
4859                 /* Can't do this on encrypted
4860                  * connections. */
4861                 return false;
4862         }
4863
4864         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4865                 return false;
4866         }
4867
4868         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4869                         CVAL(inbuf,smb_wct) != 14) {
4870                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4871                         "invalid word length.\n"));
4872                 return false;
4873         }
4874
4875         fnum = SVAL(inbuf, smb_vwv2);
4876         status = smb1srv_open_lookup(xconn,
4877                                      fnum,
4878                                      0, /* now */
4879                                      &op);
4880         if (!NT_STATUS_IS_OK(status)) {
4881                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4882                 return false;
4883         }
4884         fsp = op->compat;
4885         if (fsp == NULL) {
4886                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4887                 return false;
4888         }
4889         if (fsp->conn == NULL) {
4890                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4891                 return false;
4892         }
4893
4894         if (IS_IPC(fsp->conn)) {
4895                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4896                 return false;
4897         }
4898         if (IS_PRINT(fsp->conn)) {
4899                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4900                 return false;
4901         }
4902         doff = SVAL(inbuf,smb_vwv11);
4903
4904         numtowrite = SVAL(inbuf,smb_vwv10);
4905
4906         if (len > doff && len - doff > 0xFFFF) {
4907                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4908         }
4909
4910         if (numtowrite == 0) {
4911                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4912                 return false;
4913         }
4914
4915         /* Ensure the sizes match up. */
4916         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4917                 /* no pad byte...old smbclient :-( */
4918                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4919                         (unsigned int)doff,
4920                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4921                 return false;
4922         }
4923
4924         if (len - doff != numtowrite) {
4925                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4926                         "len = %u, doff = %u, numtowrite = %u\n",
4927                         (unsigned int)len,
4928                         (unsigned int)doff,
4929                         (unsigned int)numtowrite ));
4930                 return false;
4931         }
4932
4933         DEBUG(10,("is_valid_writeX_buffer: true "
4934                 "len = %u, doff = %u, numtowrite = %u\n",
4935                 (unsigned int)len,
4936                 (unsigned int)doff,
4937                 (unsigned int)numtowrite ));
4938
4939         return true;
4940 }
4941
4942 /****************************************************************************
4943  Reply to a write and X.
4944 ****************************************************************************/
4945
4946 void reply_write_and_X(struct smb_request *req)
4947 {
4948         connection_struct *conn = req->conn;
4949         struct smbXsrv_connection *xconn = req->xconn;
4950         files_struct *fsp;
4951         struct lock_struct lock;
4952         off_t startpos;
4953         size_t numtowrite;
4954         bool write_through;
4955         ssize_t nwritten;
4956         unsigned int smb_doff;
4957         unsigned int smblen;
4958         const char *data;
4959         NTSTATUS status;
4960         int saved_errno = 0;
4961
4962         START_PROFILE(SMBwriteX);
4963
4964         if ((req->wct != 12) && (req->wct != 14)) {
4965                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4966                 goto out;
4967         }
4968
4969         numtowrite = SVAL(req->vwv+10, 0);
4970         smb_doff = SVAL(req->vwv+11, 0);
4971         smblen = smb_len(req->inbuf);
4972
4973         if (req->unread_bytes > 0xFFFF ||
4974                         (smblen > smb_doff &&
4975                                 smblen - smb_doff > 0xFFFF)) {
4976                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4977         }
4978
4979         if (req->unread_bytes) {
4980                 /* Can't do a recvfile write on IPC$ */
4981                 if (IS_IPC(conn)) {
4982                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983                         goto out;
4984                 }
4985                 if (numtowrite != req->unread_bytes) {
4986                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987                         goto out;
4988                 }
4989         } else {
4990                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4991                                 smb_doff + numtowrite > smblen) {
4992                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4993                         goto out;
4994                 }
4995         }
4996
4997         /* If it's an IPC, pass off the pipe handler. */
4998         if (IS_IPC(conn)) {
4999                 if (req->unread_bytes) {
5000                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5001                         goto out;
5002                 }
5003                 reply_pipe_write_and_X(req);
5004                 goto out;
5005         }
5006
5007         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5008         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5009         write_through = BITSETW(req->vwv+7,0);
5010
5011         if (!check_fsp(conn, req, fsp)) {
5012                 goto out;
5013         }
5014
5015         if (!CHECK_WRITE(fsp)) {
5016                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5017                 goto out;
5018         }
5019
5020         data = smb_base(req->inbuf) + smb_doff;
5021
5022         if(req->wct == 14) {
5023                 /*
5024                  * This is a large offset (64 bit) write.
5025                  */
5026                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5027
5028         }
5029
5030         /* X/Open SMB protocol says that, unlike SMBwrite
5031         if the length is zero then NO truncation is
5032         done, just a write of zero. To truncate a file,
5033         use SMBwrite. */
5034
5035         if(numtowrite == 0) {
5036                 nwritten = 0;
5037         } else {
5038                 if (req->unread_bytes == 0) {
5039                         status = schedule_aio_write_and_X(conn,
5040                                                 req,
5041                                                 fsp,
5042                                                 data,
5043                                                 startpos,
5044                                                 numtowrite);
5045
5046                         if (NT_STATUS_IS_OK(status)) {
5047                                 /* write scheduled - we're done. */
5048                                 goto out;
5049                         }
5050                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5051                                 /* Real error - report to client. */
5052                                 reply_nterror(req, status);
5053                                 goto out;
5054                         }
5055                         /* NT_STATUS_RETRY - fall through to sync write. */
5056                 }
5057
5058                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5059                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5060                     &lock);
5061
5062                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5063                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5064                         goto out;
5065                 }
5066
5067                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5068                 saved_errno = errno;
5069
5070                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5071         }
5072
5073         if(nwritten < 0) {
5074                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5075                 goto out;
5076         }
5077
5078         if((nwritten == 0) && (numtowrite != 0)) {
5079                 reply_nterror(req, NT_STATUS_DISK_FULL);
5080                 goto out;
5081         }
5082
5083         reply_outbuf(req, 6, 0);
5084         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5085         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
5086         SSVAL(req->outbuf,smb_vwv2,nwritten);
5087         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5088
5089         DEBUG(3,("writeX %s num=%d wrote=%d\n",
5090                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5091
5092         status = sync_file(conn, fsp, write_through);
5093         if (!NT_STATUS_IS_OK(status)) {
5094                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5095                          fsp_str_dbg(fsp), nt_errstr(status)));
5096                 reply_nterror(req, status);
5097                 goto out;
5098         }
5099
5100         END_PROFILE(SMBwriteX);
5101         return;
5102
5103 out:
5104         if (req->unread_bytes) {
5105                 /* writeX failed. drain socket. */
5106                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5107                                 req->unread_bytes) {
5108                         smb_panic("failed to drain pending bytes");
5109                 }
5110                 req->unread_bytes = 0;
5111         }
5112
5113         END_PROFILE(SMBwriteX);
5114         return;
5115 }
5116
5117 /****************************************************************************
5118  Reply to a lseek.
5119 ****************************************************************************/
5120
5121 void reply_lseek(struct smb_request *req)
5122 {
5123         connection_struct *conn = req->conn;
5124         off_t startpos;
5125         off_t res= -1;
5126         int mode,umode;
5127         files_struct *fsp;
5128
5129         START_PROFILE(SMBlseek);
5130
5131         if (req->wct < 4) {
5132                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133                 END_PROFILE(SMBlseek);
5134                 return;
5135         }
5136
5137         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5138
5139         if (!check_fsp(conn, req, fsp)) {
5140                 return;
5141         }
5142
5143         flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5144
5145         mode = SVAL(req->vwv+1, 0) & 3;
5146         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5147         startpos = (off_t)IVALS(req->vwv+2, 0);
5148
5149         switch (mode) {
5150                 case 0:
5151                         umode = SEEK_SET;
5152                         res = startpos;
5153                         break;
5154                 case 1:
5155                         umode = SEEK_CUR;
5156                         res = fsp->fh->pos + startpos;
5157                         break;
5158                 case 2:
5159                         umode = SEEK_END;
5160                         break;
5161                 default:
5162                         umode = SEEK_SET;
5163                         res = startpos;
5164                         break;
5165         }
5166
5167         if (umode == SEEK_END) {
5168                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5169                         if(errno == EINVAL) {
5170                                 off_t current_pos = startpos;
5171
5172                                 if(fsp_stat(fsp) == -1) {
5173                                         reply_nterror(req,
5174                                                 map_nt_error_from_unix(errno));
5175                                         END_PROFILE(SMBlseek);
5176                                         return;
5177                                 }
5178
5179                                 current_pos += fsp->fsp_name->st.st_ex_size;
5180                                 if(current_pos < 0)
5181                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5182                         }
5183                 }
5184
5185                 if(res == -1) {
5186                         reply_nterror(req, map_nt_error_from_unix(errno));
5187                         END_PROFILE(SMBlseek);
5188                         return;
5189                 }
5190         }
5191
5192         fsp->fh->pos = res;
5193
5194         reply_outbuf(req, 2, 0);
5195         SIVAL(req->outbuf,smb_vwv0,res);
5196
5197         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5198                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5199
5200         END_PROFILE(SMBlseek);
5201         return;
5202 }
5203
5204 /****************************************************************************
5205  Reply to a flush.
5206 ****************************************************************************/
5207
5208 void reply_flush(struct smb_request *req)
5209 {
5210         connection_struct *conn = req->conn;
5211         uint16_t fnum;
5212         files_struct *fsp;
5213
5214         START_PROFILE(SMBflush);
5215
5216         if (req->wct < 1) {
5217                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5218                 return;
5219         }
5220
5221         fnum = SVAL(req->vwv+0, 0);
5222         fsp = file_fsp(req, fnum);
5223
5224         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5225                 return;
5226         }
5227
5228         if (!fsp) {
5229                 file_sync_all(conn);
5230         } else {
5231                 NTSTATUS status = sync_file(conn, fsp, True);
5232                 if (!NT_STATUS_IS_OK(status)) {
5233                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5234                                 fsp_str_dbg(fsp), nt_errstr(status)));
5235                         reply_nterror(req, status);
5236                         END_PROFILE(SMBflush);
5237                         return;
5238                 }
5239         }
5240
5241         reply_outbuf(req, 0, 0);
5242
5243         DEBUG(3,("flush\n"));
5244         END_PROFILE(SMBflush);
5245         return;
5246 }
5247
5248 /****************************************************************************
5249  Reply to a exit.
5250  conn POINTER CAN BE NULL HERE !
5251 ****************************************************************************/
5252
5253 void reply_exit(struct smb_request *req)
5254 {
5255         START_PROFILE(SMBexit);
5256
5257         file_close_pid(req->sconn, req->smbpid, req->vuid);
5258
5259         reply_outbuf(req, 0, 0);
5260
5261         DEBUG(3,("exit\n"));
5262
5263         END_PROFILE(SMBexit);
5264         return;
5265 }
5266
5267 struct reply_close_state {
5268         files_struct *fsp;
5269         struct smb_request *smbreq;
5270 };
5271
5272 static void do_smb1_close(struct tevent_req *req);
5273
5274 void reply_close(struct smb_request *req)
5275 {
5276         connection_struct *conn = req->conn;
5277         NTSTATUS status = NT_STATUS_OK;
5278         files_struct *fsp = NULL;
5279         START_PROFILE(SMBclose);
5280
5281         if (req->wct < 3) {
5282                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5283                 END_PROFILE(SMBclose);
5284                 return;
5285         }
5286
5287         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5288
5289         /*
5290          * We can only use check_fsp if we know it's not a directory.
5291          */
5292
5293         if (!check_fsp_open(conn, req, fsp)) {
5294                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5295                 END_PROFILE(SMBclose);
5296                 return;
5297         }
5298
5299         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5300                   fsp->is_directory ? "directory" : "file",
5301                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5302                   conn->num_files_open));
5303
5304         if (!fsp->is_directory) {
5305                 time_t t;
5306
5307                 /*
5308                  * Take care of any time sent in the close.
5309                  */
5310
5311                 t = srv_make_unix_date3(req->vwv+1);
5312                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5313         }
5314
5315         if (fsp->num_aio_requests != 0) {
5316
5317                 struct reply_close_state *state;
5318
5319                 DEBUG(10, ("closing with aio %u requests pending\n",
5320                            fsp->num_aio_requests));
5321
5322                 /*
5323                  * We depend on the aio_extra destructor to take care of this
5324                  * close request once fsp->num_aio_request drops to 0.
5325                  */
5326
5327                 fsp->deferred_close = tevent_wait_send(
5328                         fsp, fsp->conn->sconn->ev_ctx);
5329                 if (fsp->deferred_close == NULL) {
5330                         status = NT_STATUS_NO_MEMORY;
5331                         goto done;
5332                 }
5333
5334                 state = talloc(fsp, struct reply_close_state);
5335                 if (state == NULL) {
5336                         TALLOC_FREE(fsp->deferred_close);
5337                         status = NT_STATUS_NO_MEMORY;
5338                         goto done;
5339                 }
5340                 state->fsp = fsp;
5341                 state->smbreq = talloc_move(fsp, &req);
5342                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5343                                         state);
5344                 END_PROFILE(SMBclose);
5345                 return;
5346         }
5347
5348         /*
5349          * close_file() returns the unix errno if an error was detected on
5350          * close - normally this is due to a disk full error. If not then it
5351          * was probably an I/O error.
5352          */
5353
5354         status = close_file(req, fsp, NORMAL_CLOSE);
5355 done:
5356         if (!NT_STATUS_IS_OK(status)) {
5357                 reply_nterror(req, status);
5358                 END_PROFILE(SMBclose);
5359                 return;
5360         }
5361
5362         reply_outbuf(req, 0, 0);
5363         END_PROFILE(SMBclose);
5364         return;
5365 }
5366
5367 static void do_smb1_close(struct tevent_req *req)
5368 {
5369         struct reply_close_state *state = tevent_req_callback_data(
5370                 req, struct reply_close_state);
5371         struct smb_request *smbreq;
5372         NTSTATUS status;
5373         int ret;
5374
5375         ret = tevent_wait_recv(req);
5376         TALLOC_FREE(req);
5377         if (ret != 0) {
5378                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5379                            strerror(ret)));
5380                 /*
5381                  * Continue anyway, this should never happen
5382                  */
5383         }
5384
5385         /*
5386          * fsp->smb2_close_request right now is a talloc grandchild of
5387          * fsp. When we close_file(fsp), it would go with it. No chance to
5388          * reply...
5389          */
5390         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5391
5392         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5393         if (NT_STATUS_IS_OK(status)) {
5394                 reply_outbuf(smbreq, 0, 0);
5395         } else {
5396                 reply_nterror(smbreq, status);
5397         }
5398         if (!srv_send_smb(smbreq->xconn,
5399                         (char *)smbreq->outbuf,
5400                         true,
5401                         smbreq->seqnum+1,
5402                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5403                         NULL)) {
5404                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5405                                     "failed.");
5406         }
5407         TALLOC_FREE(smbreq);
5408 }
5409
5410 /****************************************************************************
5411  Reply to a writeclose (Core+ protocol).
5412 ****************************************************************************/
5413
5414 void reply_writeclose(struct smb_request *req)
5415 {
5416         connection_struct *conn = req->conn;
5417         size_t numtowrite;
5418         ssize_t nwritten = -1;
5419         NTSTATUS close_status = NT_STATUS_OK;
5420         off_t startpos;
5421         const char *data;
5422         struct timespec mtime;
5423         files_struct *fsp;
5424         struct lock_struct lock;
5425
5426         START_PROFILE(SMBwriteclose);
5427
5428         if (req->wct < 6) {
5429                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5430                 END_PROFILE(SMBwriteclose);
5431                 return;
5432         }
5433
5434         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5435
5436         if (!check_fsp(conn, req, fsp)) {
5437                 END_PROFILE(SMBwriteclose);
5438                 return;
5439         }
5440         if (!CHECK_WRITE(fsp)) {
5441                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5442                 END_PROFILE(SMBwriteclose);
5443                 return;
5444         }
5445
5446         numtowrite = SVAL(req->vwv+1, 0);
5447         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5448         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5449         data = (const char *)req->buf + 1;
5450
5451         if (fsp->print_file == NULL) {
5452                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5453                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5454                     &lock);
5455
5456                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5457                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5458                         END_PROFILE(SMBwriteclose);
5459                         return;
5460                 }
5461         }
5462
5463         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5464
5465         if (fsp->print_file == NULL) {
5466                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5467         }
5468
5469         set_close_write_time(fsp, mtime);
5470
5471         /*
5472          * More insanity. W2K only closes the file if writelen > 0.
5473          * JRA.
5474          */
5475
5476         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5477                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5478                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5479
5480         if (numtowrite) {
5481                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5482                          "file %s\n", fsp_str_dbg(fsp)));
5483                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5484                 fsp = NULL;
5485         }
5486
5487         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5488                 reply_nterror(req, NT_STATUS_DISK_FULL);
5489                 goto out;
5490         }
5491
5492         if(!NT_STATUS_IS_OK(close_status)) {
5493                 reply_nterror(req, close_status);
5494                 goto out;
5495         }
5496
5497         reply_outbuf(req, 1, 0);
5498
5499         SSVAL(req->outbuf,smb_vwv0,nwritten);
5500
5501 out:
5502
5503         END_PROFILE(SMBwriteclose);
5504         return;
5505 }
5506
5507 #undef DBGC_CLASS
5508 #define DBGC_CLASS DBGC_LOCKING
5509
5510 /****************************************************************************
5511  Reply to a lock.
5512 ****************************************************************************/
5513
5514 void reply_lock(struct smb_request *req)
5515 {
5516         connection_struct *conn = req->conn;
5517         uint64_t count,offset;
5518         NTSTATUS status;
5519         files_struct *fsp;
5520         struct byte_range_lock *br_lck = NULL;
5521
5522         START_PROFILE(SMBlock);
5523
5524         if (req->wct < 5) {
5525                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5526                 END_PROFILE(SMBlock);
5527                 return;
5528         }
5529
5530         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5531
5532         if (!check_fsp(conn, req, fsp)) {
5533                 END_PROFILE(SMBlock);
5534                 return;
5535         }
5536
5537         count = (uint64_t)IVAL(req->vwv+1, 0);
5538         offset = (uint64_t)IVAL(req->vwv+3, 0);
5539
5540         DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5541                  fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5542
5543         br_lck = do_lock(req->sconn->msg_ctx,
5544                         fsp,
5545                         (uint64_t)req->smbpid,
5546                         count,
5547                         offset,
5548                         WRITE_LOCK,
5549                         WINDOWS_LOCK,
5550                         False, /* Non-blocking lock. */
5551                         &status,
5552                         NULL);
5553
5554         TALLOC_FREE(br_lck);
5555
5556         if (NT_STATUS_V(status)) {
5557                 reply_nterror(req, status);
5558                 END_PROFILE(SMBlock);
5559                 return;
5560         }
5561
5562         reply_outbuf(req, 0, 0);
5563
5564         END_PROFILE(SMBlock);
5565         return;
5566 }
5567
5568 /****************************************************************************
5569  Reply to a unlock.
5570 ****************************************************************************/
5571
5572 void reply_unlock(struct smb_request *req)
5573 {
5574         connection_struct *conn = req->conn;
5575         uint64_t count,offset;
5576         NTSTATUS status;
5577         files_struct *fsp;
5578
5579         START_PROFILE(SMBunlock);
5580
5581         if (req->wct < 5) {
5582                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5583                 END_PROFILE(SMBunlock);
5584                 return;
5585         }
5586
5587         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5588
5589         if (!check_fsp(conn, req, fsp)) {
5590                 END_PROFILE(SMBunlock);
5591                 return;
5592         }
5593
5594         count = (uint64_t)IVAL(req->vwv+1, 0);
5595         offset = (uint64_t)IVAL(req->vwv+3, 0);
5596
5597         status = do_unlock(req->sconn->msg_ctx,
5598                         fsp,
5599                         (uint64_t)req->smbpid,
5600                         count,
5601                         offset,
5602                         WINDOWS_LOCK);
5603
5604         if (NT_STATUS_V(status)) {
5605                 reply_nterror(req, status);
5606                 END_PROFILE(SMBunlock);
5607                 return;
5608         }
5609
5610         DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5611                     fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5612
5613         reply_outbuf(req, 0, 0);
5614
5615         END_PROFILE(SMBunlock);
5616         return;
5617 }
5618
5619 #undef DBGC_CLASS
5620 #define DBGC_CLASS DBGC_ALL
5621
5622 /****************************************************************************
5623  Reply to a tdis.
5624  conn POINTER CAN BE NULL HERE !
5625 ****************************************************************************/
5626
5627 void reply_tdis(struct smb_request *req)
5628 {
5629         NTSTATUS status;
5630         connection_struct *conn = req->conn;
5631         struct smbXsrv_tcon *tcon;
5632
5633         START_PROFILE(SMBtdis);
5634
5635         if (!conn) {
5636                 DEBUG(4,("Invalid connection in tdis\n"));
5637                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5638                 END_PROFILE(SMBtdis);
5639                 return;
5640         }
5641
5642         tcon = conn->tcon;
5643         req->conn = NULL;
5644
5645         /*
5646          * TODO: cancel all outstanding requests on the tcon
5647          */
5648         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5649         if (!NT_STATUS_IS_OK(status)) {
5650                 DEBUG(0, ("reply_tdis: "
5651                           "smbXsrv_tcon_disconnect() failed: %s\n",
5652                           nt_errstr(status)));
5653                 /*
5654                  * If we hit this case, there is something completely
5655                  * wrong, so we better disconnect the transport connection.
5656                  */
5657                 END_PROFILE(SMBtdis);
5658                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5659                 return;
5660         }
5661
5662         TALLOC_FREE(tcon);
5663
5664         reply_outbuf(req, 0, 0);
5665         END_PROFILE(SMBtdis);
5666         return;
5667 }
5668
5669 /****************************************************************************
5670  Reply to a echo.
5671  conn POINTER CAN BE NULL HERE !
5672 ****************************************************************************/
5673
5674 void reply_echo(struct smb_request *req)
5675 {
5676         connection_struct *conn = req->conn;
5677         struct smb_perfcount_data local_pcd;
5678         struct smb_perfcount_data *cur_pcd;
5679         int smb_reverb;
5680         int seq_num;
5681
5682         START_PROFILE(SMBecho);
5683
5684         smb_init_perfcount_data(&local_pcd);
5685
5686         if (req->wct < 1) {
5687                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5688                 END_PROFILE(SMBecho);
5689                 return;
5690         }
5691
5692         smb_reverb = SVAL(req->vwv+0, 0);
5693
5694         reply_outbuf(req, 1, req->buflen);
5695
5696         /* copy any incoming data back out */
5697         if (req->buflen > 0) {
5698                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5699         }
5700
5701         if (smb_reverb > 100) {
5702                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5703                 smb_reverb = 100;
5704         }
5705
5706         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5707
5708                 /* this makes sure we catch the request pcd */
5709                 if (seq_num == smb_reverb) {
5710                         cur_pcd = &req->pcd;
5711                 } else {
5712                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5713                         cur_pcd = &local_pcd;
5714                 }
5715
5716                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5717
5718                 show_msg((char *)req->outbuf);
5719                 if (!srv_send_smb(req->xconn,
5720                                 (char *)req->outbuf,
5721                                 true, req->seqnum+1,
5722                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5723                                 cur_pcd))
5724                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5725         }
5726
5727         DEBUG(3,("echo %d times\n", smb_reverb));
5728
5729         TALLOC_FREE(req->outbuf);
5730
5731         END_PROFILE(SMBecho);
5732         return;
5733 }
5734
5735 /****************************************************************************
5736  Reply to a printopen.
5737 ****************************************************************************/
5738
5739 void reply_printopen(struct smb_request *req)
5740 {
5741         connection_struct *conn = req->conn;
5742         files_struct *fsp;
5743         NTSTATUS status;
5744
5745         START_PROFILE(SMBsplopen);
5746
5747         if (req->wct < 2) {
5748                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5749                 END_PROFILE(SMBsplopen);
5750                 return;
5751         }
5752
5753         if (!CAN_PRINT(conn)) {
5754                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5755                 END_PROFILE(SMBsplopen);
5756                 return;
5757         }
5758
5759         status = file_new(req, conn, &fsp);
5760         if(!NT_STATUS_IS_OK(status)) {
5761                 reply_nterror(req, status);
5762                 END_PROFILE(SMBsplopen);
5763                 return;
5764         }
5765
5766         /* Open for exclusive use, write only. */
5767         status = print_spool_open(fsp, NULL, req->vuid);
5768
5769         if (!NT_STATUS_IS_OK(status)) {
5770                 file_free(req, fsp);
5771                 reply_nterror(req, status);
5772                 END_PROFILE(SMBsplopen);
5773                 return;
5774         }
5775
5776         reply_outbuf(req, 1, 0);
5777         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5778
5779         DEBUG(3,("openprint fd=%d %s\n",
5780                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5781
5782         END_PROFILE(SMBsplopen);
5783         return;
5784 }
5785
5786 /****************************************************************************
5787  Reply to a printclose.
5788 ****************************************************************************/
5789
5790 void reply_printclose(struct smb_request *req)
5791 {
5792         connection_struct *conn = req->conn;
5793         files_struct *fsp;
5794         NTSTATUS status;
5795
5796         START_PROFILE(SMBsplclose);
5797
5798         if (req->wct < 1) {
5799                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5800                 END_PROFILE(SMBsplclose);
5801                 return;
5802         }
5803
5804         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5805
5806         if (!check_fsp(conn, req, fsp)) {
5807                 END_PROFILE(SMBsplclose);
5808                 return;
5809         }
5810
5811         if (!CAN_PRINT(conn)) {
5812                 reply_force_doserror(req, ERRSRV, ERRerror);
5813                 END_PROFILE(SMBsplclose);
5814                 return;
5815         }
5816
5817         DEBUG(3,("printclose fd=%d %s\n",
5818                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5819
5820         status = close_file(req, fsp, NORMAL_CLOSE);
5821
5822         if(!NT_STATUS_IS_OK(status)) {
5823                 reply_nterror(req, status);
5824                 END_PROFILE(SMBsplclose);
5825                 return;
5826         }
5827
5828         reply_outbuf(req, 0, 0);
5829
5830         END_PROFILE(SMBsplclose);
5831         return;
5832 }
5833
5834 /****************************************************************************
5835  Reply to a printqueue.
5836 ****************************************************************************/
5837
5838 void reply_printqueue(struct smb_request *req)
5839 {
5840         connection_struct *conn = req->conn;
5841         int max_count;
5842         int start_index;
5843
5844         START_PROFILE(SMBsplretq);
5845
5846         if (req->wct < 2) {
5847                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5848                 END_PROFILE(SMBsplretq);
5849                 return;
5850         }
5851
5852         max_count = SVAL(req->vwv+0, 0);
5853         start_index = SVAL(req->vwv+1, 0);
5854
5855         /* we used to allow the client to get the cnum wrong, but that
5856            is really quite gross and only worked when there was only
5857            one printer - I think we should now only accept it if they
5858            get it right (tridge) */
5859         if (!CAN_PRINT(conn)) {
5860                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5861                 END_PROFILE(SMBsplretq);
5862                 return;
5863         }
5864
5865         reply_outbuf(req, 2, 3);
5866         SSVAL(req->outbuf,smb_vwv0,0);
5867         SSVAL(req->outbuf,smb_vwv1,0);
5868         SCVAL(smb_buf(req->outbuf),0,1);
5869         SSVAL(smb_buf(req->outbuf),1,0);
5870
5871         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5872                  start_index, max_count));
5873
5874         {
5875                 TALLOC_CTX *mem_ctx = talloc_tos();
5876                 NTSTATUS status;
5877                 WERROR werr;
5878                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5879                 struct rpc_pipe_client *cli = NULL;
5880                 struct dcerpc_binding_handle *b = NULL;
5881                 struct policy_handle handle;
5882                 struct spoolss_DevmodeContainer devmode_ctr;
5883                 union spoolss_JobInfo *info;
5884                 uint32_t count;
5885                 uint32_t num_to_get;
5886                 uint32_t first;
5887                 uint32_t i;
5888
5889                 ZERO_STRUCT(handle);
5890
5891                 status = rpc_pipe_open_interface(conn,
5892                                                  &ndr_table_spoolss,
5893                                                  conn->session_info,
5894                                                  conn->sconn->remote_address,
5895                                                  conn->sconn->msg_ctx,
5896                                                  &cli);
5897                 if (!NT_STATUS_IS_OK(status)) {
5898                         DEBUG(0, ("reply_printqueue: "
5899                                   "could not connect to spoolss: %s\n",
5900                                   nt_errstr(status)));
5901                         reply_nterror(req, status);
5902                         goto out;
5903                 }
5904                 b = cli->binding_handle;
5905
5906                 ZERO_STRUCT(devmode_ctr);
5907
5908                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5909                                                 sharename,
5910                                                 NULL, devmode_ctr,
5911                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5912                                                 &handle,
5913                                                 &werr);
5914                 if (!NT_STATUS_IS_OK(status)) {
5915                         reply_nterror(req, status);
5916                         goto out;
5917                 }
5918                 if (!W_ERROR_IS_OK(werr)) {
5919                         reply_nterror(req, werror_to_ntstatus(werr));
5920                         goto out;
5921                 }
5922
5923                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5924                                                &handle,
5925                                                0, /* firstjob */
5926                                                0xff, /* numjobs */
5927                                                2, /* level */
5928                                                0, /* offered */
5929                                                &count,
5930                                                &info);
5931                 if (!W_ERROR_IS_OK(werr)) {
5932                         reply_nterror(req, werror_to_ntstatus(werr));
5933                         goto out;
5934                 }
5935
5936                 if (max_count > 0) {
5937                         first = start_index;
5938                 } else {
5939                         first = start_index + max_count + 1;
5940                 }
5941
5942                 if (first >= count) {
5943                         num_to_get = first;
5944                 } else {
5945                         num_to_get = first + MIN(ABS(max_count), count - first);
5946                 }
5947
5948                 for (i = first; i < num_to_get; i++) {
5949                         char blob[28];
5950                         char *p = blob;
5951                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5952                         int qstatus;
5953                         size_t len = 0;
5954                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5955                                                         info[i].info2.job_id);
5956
5957                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5958                                 qstatus = 2;
5959                         } else {
5960                                 qstatus = 3;
5961                         }
5962
5963                         srv_put_dos_date2(p, 0, qtime);
5964                         SCVAL(p, 4, qstatus);
5965                         SSVAL(p, 5, qrapjobid);
5966                         SIVAL(p, 7, info[i].info2.size);
5967                         SCVAL(p, 11, 0);
5968                         status = srvstr_push(blob, req->flags2, p+12,
5969                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
5970                         if (!NT_STATUS_IS_OK(status)) {
5971                                 reply_nterror(req, status);
5972                                 goto out;
5973                         }
5974                         if (message_push_blob(
5975                                     &req->outbuf,
5976                                     data_blob_const(
5977                                             blob, sizeof(blob))) == -1) {
5978                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5979                                 goto out;
5980                         }
5981                 }
5982
5983                 if (count > 0) {
5984                         SSVAL(req->outbuf,smb_vwv0,count);
5985                         SSVAL(req->outbuf,smb_vwv1,
5986                               (max_count>0?first+count:first-1));
5987                         SCVAL(smb_buf(req->outbuf),0,1);
5988                         SSVAL(smb_buf(req->outbuf),1,28*count);
5989                 }
5990
5991
5992                 DEBUG(3, ("%u entries returned in queue\n",
5993                           (unsigned)count));
5994
5995 out:
5996                 if (b && is_valid_policy_hnd(&handle)) {
5997                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5998                 }
5999
6000         }
6001
6002         END_PROFILE(SMBsplretq);
6003         return;
6004 }
6005
6006 /****************************************************************************
6007  Reply to a printwrite.
6008 ****************************************************************************/
6009
6010 void reply_printwrite(struct smb_request *req)
6011 {
6012         connection_struct *conn = req->conn;
6013         int numtowrite;
6014         const char *data;
6015         files_struct *fsp;
6016
6017         START_PROFILE(SMBsplwr);
6018
6019         if (req->wct < 1) {
6020                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6021                 END_PROFILE(SMBsplwr);
6022                 return;
6023         }
6024
6025         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6026
6027         if (!check_fsp(conn, req, fsp)) {
6028                 END_PROFILE(SMBsplwr);
6029                 return;
6030         }
6031
6032         if (!fsp->print_file) {
6033                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6034                 END_PROFILE(SMBsplwr);
6035                 return;
6036         }
6037
6038         if (!CHECK_WRITE(fsp)) {
6039                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6040                 END_PROFILE(SMBsplwr);
6041                 return;
6042         }
6043
6044         numtowrite = SVAL(req->buf, 1);
6045
6046         if (req->buflen < numtowrite + 3) {
6047                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6048                 END_PROFILE(SMBsplwr);
6049                 return;
6050         }
6051
6052         data = (const char *)req->buf + 3;
6053
6054         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6055                 reply_nterror(req, map_nt_error_from_unix(errno));
6056                 END_PROFILE(SMBsplwr);
6057                 return;
6058         }
6059
6060         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6061
6062         END_PROFILE(SMBsplwr);
6063         return;
6064 }
6065
6066 /****************************************************************************
6067  Reply to a mkdir.
6068 ****************************************************************************/
6069
6070 void reply_mkdir(struct smb_request *req)
6071 {
6072         connection_struct *conn = req->conn;
6073         struct smb_filename *smb_dname = NULL;
6074         char *directory = NULL;
6075         NTSTATUS status;
6076         uint32_t ucf_flags = UCF_PREP_CREATEFILE |
6077                         (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6078         TALLOC_CTX *ctx = talloc_tos();
6079
6080         START_PROFILE(SMBmkdir);
6081
6082         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6083                             STR_TERMINATE, &status);
6084         if (!NT_STATUS_IS_OK(status)) {
6085                 reply_nterror(req, status);
6086                 goto out;
6087         }
6088
6089         status = filename_convert(ctx, conn,
6090                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
6091                                  directory,
6092                                  ucf_flags,
6093                                  NULL,
6094                                  &smb_dname);
6095         if (!NT_STATUS_IS_OK(status)) {
6096                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6097                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6098                                         ERRSRV, ERRbadpath);
6099                         goto out;
6100                 }
6101                 reply_nterror(req, status);
6102                 goto out;
6103         }
6104
6105         status = create_directory(conn, req, smb_dname);
6106
6107         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6108
6109         if (!NT_STATUS_IS_OK(status)) {
6110
6111                 if (!use_nt_status()
6112                     && NT_STATUS_EQUAL(status,
6113                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
6114                         /*
6115                          * Yes, in the DOS error code case we get a
6116                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6117                          * samba4 torture test.
6118                          */
6119                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6120                 }
6121
6122                 reply_nterror(req, status);
6123                 goto out;
6124         }
6125
6126         reply_outbuf(req, 0, 0);
6127
6128         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6129  out:
6130         TALLOC_FREE(smb_dname);
6131         END_PROFILE(SMBmkdir);
6132         return;
6133 }
6134
6135 /****************************************************************************
6136  Reply to a rmdir.
6137 ****************************************************************************/
6138
6139 void reply_rmdir(struct smb_request *req)
6140 {
6141         connection_struct *conn = req->conn;
6142         struct smb_filename *smb_dname = NULL;
6143         char *directory = NULL;
6144         NTSTATUS status;
6145         TALLOC_CTX *ctx = talloc_tos();
6146         files_struct *fsp = NULL;
6147         int info = 0;
6148         uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6149         struct smbd_server_connection *sconn = req->sconn;
6150
6151         START_PROFILE(SMBrmdir);
6152
6153         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6154                             STR_TERMINATE, &status);
6155         if (!NT_STATUS_IS_OK(status)) {
6156                 reply_nterror(req, status);
6157                 goto out;
6158         }
6159
6160         status = filename_convert(ctx, conn,
6161                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
6162                                  directory,
6163                                  ucf_flags,
6164                                  NULL,
6165                                  &smb_dname);
6166         if (!NT_STATUS_IS_OK(status)) {
6167                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6168                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6169                                         ERRSRV, ERRbadpath);
6170                         goto out;
6171                 }
6172                 reply_nterror(req, status);
6173                 goto out;
6174         }
6175
6176         if (is_ntfs_stream_smb_fname(smb_dname)) {
6177                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6178                 goto out;
6179         }
6180
6181         status = SMB_VFS_CREATE_FILE(
6182                 conn,                                   /* conn */
6183                 req,                                    /* req */
6184                 0,                                      /* root_dir_fid */
6185                 smb_dname,                              /* fname */
6186                 DELETE_ACCESS,                          /* access_mask */
6187                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6188                         FILE_SHARE_DELETE),
6189                 FILE_OPEN,                              /* create_disposition*/
6190                 FILE_DIRECTORY_FILE,                    /* create_options */
6191                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6192                 0,                                      /* oplock_request */
6193                 NULL,                                   /* lease */
6194                 0,                                      /* allocation_size */
6195                 0,                                      /* private_flags */
6196                 NULL,                                   /* sd */
6197                 NULL,                                   /* ea_list */
6198                 &fsp,                                   /* result */
6199                 &info,                                  /* pinfo */
6200                 NULL, NULL);                            /* create context */
6201
6202         if (!NT_STATUS_IS_OK(status)) {
6203                 if (open_was_deferred(req->xconn, req->mid)) {
6204                         /* We have re-scheduled this call. */
6205                         goto out;
6206                 }
6207                 reply_nterror(req, status);
6208                 goto out;
6209         }
6210
6211         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6212         if (!NT_STATUS_IS_OK(status)) {
6213                 close_file(req, fsp, ERROR_CLOSE);
6214                 reply_nterror(req, status);
6215                 goto out;
6216         }
6217
6218         if (!set_delete_on_close(fsp, true,
6219                         conn->session_info->security_token,
6220                         conn->session_info->unix_token)) {
6221                 close_file(req, fsp, ERROR_CLOSE);
6222                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6223                 goto out;
6224         }
6225
6226         status = close_file(req, fsp, NORMAL_CLOSE);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 reply_nterror(req, status);
6229         } else {
6230                 reply_outbuf(req, 0, 0);
6231         }
6232
6233         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6234
6235         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6236  out:
6237         TALLOC_FREE(smb_dname);
6238         END_PROFILE(SMBrmdir);
6239         return;
6240 }
6241
6242 /*******************************************************************
6243  Resolve wildcards in a filename rename.
6244 ********************************************************************/
6245
6246 static bool resolve_wildcards(TALLOC_CTX *ctx,
6247                                 const char *name1,
6248                                 const char *name2,
6249                                 char **pp_newname)
6250 {
6251         char *name2_copy = NULL;
6252         char *root1 = NULL;
6253         char *root2 = NULL;
6254         char *ext1 = NULL;
6255         char *ext2 = NULL;
6256         char *p,*p2, *pname1, *pname2;
6257
6258         name2_copy = talloc_strdup(ctx, name2);
6259         if (!name2_copy) {
6260                 return False;
6261         }
6262
6263         pname1 = strrchr_m(name1,'/');
6264         pname2 = strrchr_m(name2_copy,'/');
6265
6266         if (!pname1 || !pname2) {
6267                 return False;
6268         }
6269
6270         /* Truncate the copy of name2 at the last '/' */
6271         *pname2 = '\0';
6272
6273         /* Now go past the '/' */
6274         pname1++;
6275         pname2++;
6276
6277         root1 = talloc_strdup(ctx, pname1);
6278         root2 = talloc_strdup(ctx, pname2);
6279
6280         if (!root1 || !root2) {
6281                 return False;
6282         }
6283
6284         p = strrchr_m(root1,'.');
6285         if (p) {
6286                 *p = 0;
6287                 ext1 = talloc_strdup(ctx, p+1);
6288         } else {
6289                 ext1 = talloc_strdup(ctx, "");
6290         }
6291         p = strrchr_m(root2,'.');
6292         if (p) {
6293                 *p = 0;
6294                 ext2 = talloc_strdup(ctx, p+1);
6295         } else {
6296                 ext2 = talloc_strdup(ctx, "");
6297         }
6298
6299         if (!ext1 || !ext2) {
6300                 return False;
6301         }
6302
6303         p = root1;
6304         p2 = root2;
6305         while (*p2) {
6306                 if (*p2 == '?') {
6307                         /* Hmmm. Should this be mb-aware ? */
6308                         *p2 = *p;
6309                         p2++;
6310                 } else if (*p2 == '*') {
6311                         *p2 = '\0';
6312                         root2 = talloc_asprintf(ctx, "%s%s",
6313                                                 root2,
6314                                                 p);
6315                         if (!root2) {
6316                                 return False;
6317                         }
6318                         break;
6319                 } else {
6320                         p2++;
6321                 }
6322                 if (*p) {
6323                         p++;
6324                 }
6325         }
6326
6327         p = ext1;
6328         p2 = ext2;
6329         while (*p2) {
6330                 if (*p2 == '?') {
6331                         /* Hmmm. Should this be mb-aware ? */
6332                         *p2 = *p;
6333                         p2++;
6334                 } else if (*p2 == '*') {
6335                         *p2 = '\0';
6336                         ext2 = talloc_asprintf(ctx, "%s%s",
6337                                                 ext2,
6338                                                 p);
6339                         if (!ext2) {
6340                                 return False;
6341                         }
6342                         break;
6343                 } else {
6344                         p2++;
6345                 }
6346                 if (*p) {
6347                         p++;
6348                 }
6349         }
6350
6351         if (*ext2) {
6352                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6353                                 name2_copy,
6354                                 root2,
6355                                 ext2);
6356         } else {
6357                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6358                                 name2_copy,
6359                                 root2);
6360         }
6361
6362         if (!*pp_newname) {
6363                 return False;
6364         }
6365
6366         return True;
6367 }
6368
6369 /****************************************************************************
6370  Ensure open files have their names updated. Updated to notify other smbd's
6371  asynchronously.
6372 ****************************************************************************/
6373
6374 static void rename_open_files(connection_struct *conn,
6375                               struct share_mode_lock *lck,
6376                               struct file_id id,
6377                               uint32_t orig_name_hash,
6378                               const struct smb_filename *smb_fname_dst)
6379 {
6380         files_struct *fsp;
6381         bool did_rename = False;
6382         NTSTATUS status;
6383         uint32_t new_name_hash = 0;
6384
6385         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6386             fsp = file_find_di_next(fsp)) {
6387                 /* fsp_name is a relative path under the fsp. To change this for other
6388                    sharepaths we need to manipulate relative paths. */
6389                 /* TODO - create the absolute path and manipulate the newname
6390                    relative to the sharepath. */
6391                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6392                         continue;
6393                 }
6394                 if (fsp->name_hash != orig_name_hash) {
6395                         continue;
6396                 }
6397                 DEBUG(10, ("rename_open_files: renaming file %s "
6398                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6399                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6400                            smb_fname_str_dbg(smb_fname_dst)));
6401
6402                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6403                 if (NT_STATUS_IS_OK(status)) {
6404                         did_rename = True;
6405                         new_name_hash = fsp->name_hash;
6406                 }
6407         }
6408
6409         if (!did_rename) {
6410                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6411                            "for %s\n", file_id_string_tos(&id),
6412                            smb_fname_str_dbg(smb_fname_dst)));
6413         }
6414
6415         /* Send messages to all smbd's (not ourself) that the name has changed. */
6416         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6417                               orig_name_hash, new_name_hash,
6418                               smb_fname_dst);
6419
6420 }
6421
6422 /****************************************************************************
6423  We need to check if the source path is a parent directory of the destination
6424  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6425  refuse the rename with a sharing violation. Under UNIX the above call can
6426  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6427  probably need to check that the client is a Windows one before disallowing
6428  this as a UNIX client (one with UNIX extensions) can know the source is a
6429  symlink and make this decision intelligently. Found by an excellent bug
6430  report from <AndyLiebman@aol.com>.
6431 ****************************************************************************/
6432
6433 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6434                                      const struct smb_filename *smb_fname_dst)
6435 {
6436         const char *psrc = smb_fname_src->base_name;
6437         const char *pdst = smb_fname_dst->base_name;
6438         size_t slen;
6439
6440         if (psrc[0] == '.' && psrc[1] == '/') {
6441                 psrc += 2;
6442         }
6443         if (pdst[0] == '.' && pdst[1] == '/') {
6444                 pdst += 2;
6445         }
6446         if ((slen = strlen(psrc)) > strlen(pdst)) {
6447                 return False;
6448         }
6449         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6450 }
6451
6452 /*
6453  * Do the notify calls from a rename
6454  */
6455
6456 static void notify_rename(connection_struct *conn, bool is_dir,
6457                           const struct smb_filename *smb_fname_src,
6458                           const struct smb_filename *smb_fname_dst)
6459 {
6460         char *parent_dir_src = NULL;
6461         char *parent_dir_dst = NULL;
6462         uint32_t mask;
6463
6464         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6465                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6466
6467         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6468                             &parent_dir_src, NULL) ||
6469             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6470                             &parent_dir_dst, NULL)) {
6471                 goto out;
6472         }
6473
6474         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6475                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6476                              smb_fname_src->base_name);
6477                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6478                              smb_fname_dst->base_name);
6479         }
6480         else {
6481                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6482                              smb_fname_src->base_name);
6483                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6484                              smb_fname_dst->base_name);
6485         }
6486
6487         /* this is a strange one. w2k3 gives an additional event for
6488            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6489            files, but not directories */
6490         if (!is_dir) {
6491                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6492                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6493                              |FILE_NOTIFY_CHANGE_CREATION,
6494                              smb_fname_dst->base_name);
6495         }
6496  out:
6497         TALLOC_FREE(parent_dir_src);
6498         TALLOC_FREE(parent_dir_dst);
6499 }
6500
6501 /****************************************************************************
6502  Returns an error if the parent directory for a filename is open in an
6503  incompatible way.
6504 ****************************************************************************/
6505
6506 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6507                                         const struct smb_filename *smb_fname_dst_in)
6508 {
6509         char *parent_dir = NULL;
6510         struct smb_filename smb_fname_parent;
6511         struct file_id id;
6512         files_struct *fsp = NULL;
6513         int ret;
6514
6515         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6516                         &parent_dir, NULL)) {
6517                 return NT_STATUS_NO_MEMORY;
6518         }
6519         ZERO_STRUCT(smb_fname_parent);
6520         smb_fname_parent.base_name = parent_dir;
6521
6522         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6523         if (ret == -1) {
6524                 return map_nt_error_from_unix(errno);
6525         }
6526
6527         /*
6528          * We're only checking on this smbd here, mostly good
6529          * enough.. and will pass tests.
6530          */
6531
6532         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6533         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6534                         fsp = file_find_di_next(fsp)) {
6535                 if (fsp->access_mask & DELETE_ACCESS) {
6536                         return NT_STATUS_SHARING_VIOLATION;
6537                 }
6538         }
6539         return NT_STATUS_OK;
6540 }
6541
6542 /****************************************************************************
6543  Rename an open file - given an fsp.
6544 ****************************************************************************/
6545
6546 NTSTATUS rename_internals_fsp(connection_struct *conn,
6547                         files_struct *fsp,
6548                         const struct smb_filename *smb_fname_dst_in,
6549                         uint32_t attrs,
6550                         bool replace_if_exists)
6551 {
6552         TALLOC_CTX *ctx = talloc_tos();
6553         struct smb_filename *smb_fname_dst = NULL;
6554         NTSTATUS status = NT_STATUS_OK;
6555         struct share_mode_lock *lck = NULL;
6556         bool dst_exists, old_is_stream, new_is_stream;
6557
6558         status = check_name(conn, smb_fname_dst_in->base_name);
6559         if (!NT_STATUS_IS_OK(status)) {
6560                 return status;
6561         }
6562
6563         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6564         if (!NT_STATUS_IS_OK(status)) {
6565                 return status;
6566         }
6567
6568         /* Make a copy of the dst smb_fname structs */
6569
6570         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6571         if (smb_fname_dst == NULL) {
6572                 status = NT_STATUS_NO_MEMORY;
6573                 goto out;
6574         }
6575
6576         /*
6577          * Check for special case with case preserving and not
6578          * case sensitive. If the new last component differs from the original
6579          * last component only by case, then we should allow
6580          * the rename (user is trying to change the case of the
6581          * filename).
6582          */
6583         if (!conn->case_sensitive && conn->case_preserve &&
6584             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6585             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6586                 char *last_slash;
6587                 char *fname_dst_lcomp_base_mod = NULL;
6588                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6589
6590                 /*
6591                  * Get the last component of the destination name.
6592                  */
6593                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6594                 if (last_slash) {
6595                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6596                 } else {
6597                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6598                 }
6599                 if (!fname_dst_lcomp_base_mod) {
6600                         status = NT_STATUS_NO_MEMORY;
6601                         goto out;
6602                 }
6603
6604                 /*
6605                  * Create an smb_filename struct using the original last
6606                  * component of the destination.
6607                  */
6608                 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6609                         ctx, smb_fname_dst->original_lcomp, NULL);
6610                 if (smb_fname_orig_lcomp == NULL) {
6611                         status = NT_STATUS_NO_MEMORY;
6612                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6613                         goto out;
6614                 }
6615
6616                 /* If the base names only differ by case, use original. */
6617                 if(!strcsequal(fname_dst_lcomp_base_mod,
6618                                smb_fname_orig_lcomp->base_name)) {
6619                         char *tmp;
6620                         /*
6621                          * Replace the modified last component with the
6622                          * original.
6623                          */
6624                         if (last_slash) {
6625                                 *last_slash = '\0'; /* Truncate at the '/' */
6626                                 tmp = talloc_asprintf(smb_fname_dst,
6627                                         "%s/%s",
6628                                         smb_fname_dst->base_name,
6629                                         smb_fname_orig_lcomp->base_name);
6630                         } else {
6631                                 tmp = talloc_asprintf(smb_fname_dst,
6632                                         "%s",
6633                                         smb_fname_orig_lcomp->base_name);
6634                         }
6635                         if (tmp == NULL) {
6636                                 status = NT_STATUS_NO_MEMORY;
6637                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6638                                 TALLOC_FREE(smb_fname_orig_lcomp);
6639                                 goto out;
6640                         }
6641                         TALLOC_FREE(smb_fname_dst->base_name);
6642                         smb_fname_dst->base_name = tmp;
6643                 }
6644
6645                 /* If the stream_names only differ by case, use original. */
6646                 if(!strcsequal(smb_fname_dst->stream_name,
6647                                smb_fname_orig_lcomp->stream_name)) {
6648                         char *tmp = NULL;
6649                         /* Use the original stream. */
6650                         tmp = talloc_strdup(smb_fname_dst,
6651                                             smb_fname_orig_lcomp->stream_name);
6652                         if (tmp == NULL) {
6653                                 status = NT_STATUS_NO_MEMORY;
6654                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6655                                 TALLOC_FREE(smb_fname_orig_lcomp);
6656                                 goto out;
6657                         }
6658                         TALLOC_FREE(smb_fname_dst->stream_name);
6659                         smb_fname_dst->stream_name = tmp;
6660                 }
6661                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6662                 TALLOC_FREE(smb_fname_orig_lcomp);
6663         }
6664
6665         /*
6666          * If the src and dest names are identical - including case,
6667          * don't do the rename, just return success.
6668          */
6669
6670         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6671             strcsequal(fsp->fsp_name->stream_name,
6672                        smb_fname_dst->stream_name)) {
6673                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6674                           "- returning success\n",
6675                           smb_fname_str_dbg(smb_fname_dst)));
6676                 status = NT_STATUS_OK;
6677                 goto out;
6678         }
6679
6680         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6681         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6682
6683         /* Return the correct error code if both names aren't streams. */
6684         if (!old_is_stream && new_is_stream) {
6685                 status = NT_STATUS_OBJECT_NAME_INVALID;
6686                 goto out;
6687         }
6688
6689         if (old_is_stream && !new_is_stream) {
6690                 status = NT_STATUS_INVALID_PARAMETER;
6691                 goto out;
6692         }
6693
6694         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6695
6696         if(!replace_if_exists && dst_exists) {
6697                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6698                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6699                           smb_fname_str_dbg(smb_fname_dst)));
6700                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6701                 goto out;
6702         }
6703
6704         if (dst_exists) {
6705                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6706                     &smb_fname_dst->st);
6707                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6708                                                            fileid);
6709                 /* The file can be open when renaming a stream */
6710                 if (dst_fsp && !new_is_stream) {
6711                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6712                         status = NT_STATUS_ACCESS_DENIED;
6713                         goto out;
6714                 }
6715         }
6716
6717         /* Ensure we have a valid stat struct for the source. */
6718         status = vfs_stat_fsp(fsp);
6719         if (!NT_STATUS_IS_OK(status)) {
6720                 goto out;
6721         }
6722
6723         status = can_rename(conn, fsp, attrs);
6724
6725         if (!NT_STATUS_IS_OK(status)) {
6726                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6727                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6728                           smb_fname_str_dbg(smb_fname_dst)));
6729                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6730                         status = NT_STATUS_ACCESS_DENIED;
6731                 goto out;
6732         }
6733
6734         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6735                 status = NT_STATUS_ACCESS_DENIED;
6736         }
6737
6738         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6739
6740         /*
6741          * We have the file open ourselves, so not being able to get the
6742          * corresponding share mode lock is a fatal error.
6743          */
6744
6745         SMB_ASSERT(lck != NULL);
6746
6747         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6748                 uint32_t create_options = fsp->fh->private_options;
6749
6750                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6751                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6752                           smb_fname_str_dbg(smb_fname_dst)));
6753
6754                 if (!fsp->is_directory &&
6755                     !lp_posix_pathnames() &&
6756                     (lp_map_archive(SNUM(conn)) ||
6757                     lp_store_dos_attributes(SNUM(conn)))) {
6758                         /* We must set the archive bit on the newly
6759                            renamed file. */
6760                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6761                                 uint32_t old_dosmode = dos_mode(conn,
6762                                                         smb_fname_dst);
6763                                 file_set_dosmode(conn,
6764                                         smb_fname_dst,
6765                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6766                                         NULL,
6767                                         true);
6768                         }
6769                 }
6770
6771                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6772                               smb_fname_dst);
6773
6774                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6775                                   smb_fname_dst);
6776
6777                 /*
6778                  * A rename acts as a new file create w.r.t. allowing an initial delete
6779                  * on close, probably because in Windows there is a new handle to the
6780                  * new file. If initial delete on close was requested but not
6781                  * originally set, we need to set it here. This is probably not 100% correct,
6782                  * but will work for the CIFSFS client which in non-posix mode
6783                  * depends on these semantics. JRA.
6784                  */
6785
6786                 if (create_options & FILE_DELETE_ON_CLOSE) {
6787                         status = can_set_delete_on_close(fsp, 0);
6788
6789                         if (NT_STATUS_IS_OK(status)) {
6790                                 /* Note that here we set the *inital* delete on close flag,
6791                                  * not the regular one. The magic gets handled in close. */
6792                                 fsp->initial_delete_on_close = True;
6793                         }
6794                 }
6795                 TALLOC_FREE(lck);
6796                 status = NT_STATUS_OK;
6797                 goto out;
6798         }
6799
6800         TALLOC_FREE(lck);
6801
6802         if (errno == ENOTDIR || errno == EISDIR) {
6803                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6804         } else {
6805                 status = map_nt_error_from_unix(errno);
6806         }
6807
6808         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6809                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6810                   smb_fname_str_dbg(smb_fname_dst)));
6811
6812  out:
6813         TALLOC_FREE(smb_fname_dst);
6814
6815         return status;
6816 }
6817
6818 /****************************************************************************
6819  The guts of the rename command, split out so it may be called by the NT SMB
6820  code.
6821 ****************************************************************************/
6822
6823 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6824                         connection_struct *conn,
6825                         struct smb_request *req,
6826                         struct smb_filename *smb_fname_src,
6827                         struct smb_filename *smb_fname_dst,
6828                         uint32_t attrs,
6829                         bool replace_if_exists,
6830                         bool src_has_wild,
6831                         bool dest_has_wild,
6832                         uint32_t access_mask)
6833 {
6834         char *fname_src_dir = NULL;
6835         char *fname_src_mask = NULL;
6836         int count=0;
6837         NTSTATUS status = NT_STATUS_OK;
6838         struct smb_Dir *dir_hnd = NULL;
6839         const char *dname = NULL;
6840         char *talloced = NULL;
6841         long offset = 0;
6842         int create_options = 0;
6843         bool posix_pathnames = lp_posix_pathnames();
6844         int rc;
6845
6846         /*
6847          * Split the old name into directory and last component
6848          * strings. Note that unix_convert may have stripped off a
6849          * leading ./ from both name and newname if the rename is
6850          * at the root of the share. We need to make sure either both
6851          * name and newname contain a / character or neither of them do
6852          * as this is checked in resolve_wildcards().
6853          */
6854
6855         /* Split up the directory from the filename/mask. */
6856         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6857                                       &fname_src_dir, &fname_src_mask);
6858         if (!NT_STATUS_IS_OK(status)) {
6859                 status = NT_STATUS_NO_MEMORY;
6860                 goto out;
6861         }
6862
6863         /*
6864          * We should only check the mangled cache
6865          * here if unix_convert failed. This means
6866          * that the path in 'mask' doesn't exist
6867          * on the file system and so we need to look
6868          * for a possible mangle. This patch from
6869          * Tine Smukavec <valentin.smukavec@hermes.si>.
6870          */
6871
6872         if (!VALID_STAT(smb_fname_src->st) &&
6873             mangle_is_mangled(fname_src_mask, conn->params)) {
6874                 char *new_mask = NULL;
6875                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6876                                             conn->params);
6877                 if (new_mask) {
6878                         TALLOC_FREE(fname_src_mask);
6879                         fname_src_mask = new_mask;
6880                 }
6881         }
6882
6883         if (!src_has_wild) {
6884                 files_struct *fsp;
6885
6886                 /*
6887                  * Only one file needs to be renamed. Append the mask back
6888                  * onto the directory.
6889                  */
6890                 TALLOC_FREE(smb_fname_src->base_name);
6891                 if (ISDOT(fname_src_dir)) {
6892                         /* Ensure we use canonical names on open. */
6893                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6894                                                         "%s",
6895                                                         fname_src_mask);
6896                 } else {
6897                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6898                                                         "%s/%s",
6899                                                         fname_src_dir,
6900                                                         fname_src_mask);
6901                 }
6902                 if (!smb_fname_src->base_name) {
6903                         status = NT_STATUS_NO_MEMORY;
6904                         goto out;
6905                 }
6906
6907                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6908                           "case_preserve = %d, short case preserve = %d, "
6909                           "directory = %s, newname = %s, "
6910                           "last_component_dest = %s\n",
6911                           conn->case_sensitive, conn->case_preserve,
6912                           conn->short_case_preserve,
6913                           smb_fname_str_dbg(smb_fname_src),
6914                           smb_fname_str_dbg(smb_fname_dst),
6915                           smb_fname_dst->original_lcomp));
6916
6917                 /* The dest name still may have wildcards. */
6918                 if (dest_has_wild) {
6919                         char *fname_dst_mod = NULL;
6920                         if (!resolve_wildcards(smb_fname_dst,
6921                                                smb_fname_src->base_name,
6922                                                smb_fname_dst->base_name,
6923                                                &fname_dst_mod)) {
6924                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6925                                           "%s %s failed\n",
6926                                           smb_fname_src->base_name,
6927                                           smb_fname_dst->base_name));
6928                                 status = NT_STATUS_NO_MEMORY;
6929                                 goto out;
6930                         }
6931                         TALLOC_FREE(smb_fname_dst->base_name);
6932                         smb_fname_dst->base_name = fname_dst_mod;
6933                 }
6934
6935                 ZERO_STRUCT(smb_fname_src->st);
6936                 if (posix_pathnames) {
6937                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6938                 } else {
6939                         rc = SMB_VFS_STAT(conn, smb_fname_src);
6940                 }
6941                 if (rc == -1) {
6942                         status = map_nt_error_from_unix_common(errno);
6943                         goto out;
6944                 }
6945
6946                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6947                         create_options |= FILE_DIRECTORY_FILE;
6948                 }
6949
6950                 status = SMB_VFS_CREATE_FILE(
6951                         conn,                           /* conn */
6952                         req,                            /* req */
6953                         0,                              /* root_dir_fid */
6954                         smb_fname_src,                  /* fname */
6955                         access_mask,                    /* access_mask */
6956                         (FILE_SHARE_READ |              /* share_access */
6957                             FILE_SHARE_WRITE),
6958                         FILE_OPEN,                      /* create_disposition*/
6959                         create_options,                 /* create_options */
6960                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6961                         0,                              /* oplock_request */
6962                         NULL,                           /* lease */
6963                         0,                              /* allocation_size */
6964                         0,                              /* private_flags */
6965                         NULL,                           /* sd */
6966                         NULL,                           /* ea_list */
6967                         &fsp,                           /* result */
6968                         NULL,                           /* pinfo */
6969                         NULL, NULL);                    /* create context */
6970
6971                 if (!NT_STATUS_IS_OK(status)) {
6972                         DEBUG(3, ("Could not open rename source %s: %s\n",
6973                                   smb_fname_str_dbg(smb_fname_src),
6974                                   nt_errstr(status)));
6975                         goto out;
6976                 }
6977
6978                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6979                                               attrs, replace_if_exists);
6980
6981                 close_file(req, fsp, NORMAL_CLOSE);
6982
6983                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6984                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6985                           smb_fname_str_dbg(smb_fname_dst)));
6986
6987                 goto out;
6988         }
6989
6990         /*
6991          * Wildcards - process each file that matches.
6992          */
6993         if (strequal(fname_src_mask, "????????.???")) {
6994                 TALLOC_FREE(fname_src_mask);
6995                 fname_src_mask = talloc_strdup(ctx, "*");
6996                 if (!fname_src_mask) {
6997                         status = NT_STATUS_NO_MEMORY;
6998                         goto out;
6999                 }
7000         }
7001
7002         status = check_name(conn, fname_src_dir);
7003         if (!NT_STATUS_IS_OK(status)) {
7004                 goto out;
7005         }
7006
7007         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
7008                           attrs);
7009         if (dir_hnd == NULL) {
7010                 status = map_nt_error_from_unix(errno);
7011                 goto out;
7012         }
7013
7014         status = NT_STATUS_NO_SUCH_FILE;
7015         /*
7016          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7017          * - gentest fix. JRA
7018          */
7019
7020         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7021                                     &talloced))) {
7022                 files_struct *fsp = NULL;
7023                 char *destname = NULL;
7024                 bool sysdir_entry = False;
7025
7026                 /* Quick check for "." and ".." */
7027                 if (ISDOT(dname) || ISDOTDOT(dname)) {
7028                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7029                                 sysdir_entry = True;
7030                         } else {
7031                                 TALLOC_FREE(talloced);
7032                                 continue;
7033                         }
7034                 }
7035
7036                 if (!is_visible_file(conn, fname_src_dir, dname,
7037                                      &smb_fname_src->st, false)) {
7038                         TALLOC_FREE(talloced);
7039                         continue;
7040                 }
7041
7042                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7043                         TALLOC_FREE(talloced);
7044                         continue;
7045                 }
7046
7047                 if (sysdir_entry) {
7048                         status = NT_STATUS_OBJECT_NAME_INVALID;
7049                         break;
7050                 }
7051
7052                 TALLOC_FREE(smb_fname_src->base_name);
7053                 if (ISDOT(fname_src_dir)) {
7054                         /* Ensure we use canonical names on open. */
7055                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7056                                                         "%s",
7057                                                         dname);
7058                 } else {
7059                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7060                                                         "%s/%s",
7061                                                         fname_src_dir,
7062                                                         dname);
7063                 }
7064                 if (!smb_fname_src->base_name) {
7065                         status = NT_STATUS_NO_MEMORY;
7066                         goto out;
7067                 }
7068
7069                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7070                                        smb_fname_dst->base_name,
7071                                        &destname)) {
7072                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
7073                                   smb_fname_src->base_name, destname));
7074                         TALLOC_FREE(talloced);
7075                         continue;
7076                 }
7077                 if (!destname) {
7078                         status = NT_STATUS_NO_MEMORY;
7079                         goto out;
7080                 }
7081
7082                 TALLOC_FREE(smb_fname_dst->base_name);
7083                 smb_fname_dst->base_name = destname;
7084
7085                 ZERO_STRUCT(smb_fname_src->st);
7086                 if (posix_pathnames) {
7087                         SMB_VFS_LSTAT(conn, smb_fname_src);
7088                 } else {
7089                         SMB_VFS_STAT(conn, smb_fname_src);
7090                 }
7091
7092                 create_options = 0;
7093
7094                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7095                         create_options |= FILE_DIRECTORY_FILE;
7096                 }
7097
7098                 status = SMB_VFS_CREATE_FILE(
7099                         conn,                           /* conn */
7100                         req,                            /* req */
7101                         0,                              /* root_dir_fid */
7102                         smb_fname_src,                  /* fname */
7103                         access_mask,                    /* access_mask */
7104                         (FILE_SHARE_READ |              /* share_access */
7105                             FILE_SHARE_WRITE),
7106                         FILE_OPEN,                      /* create_disposition*/
7107                         create_options,                 /* create_options */
7108                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7109                         0,                              /* oplock_request */
7110                         NULL,                           /* lease */
7111                         0,                              /* allocation_size */
7112                         0,                              /* private_flags */
7113                         NULL,                           /* sd */
7114                         NULL,                           /* ea_list */
7115                         &fsp,                           /* result */
7116                         NULL,                           /* pinfo */
7117                         NULL, NULL);                    /* create context */
7118
7119                 if (!NT_STATUS_IS_OK(status)) {
7120                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7121                                  "returned %s rename %s -> %s\n",
7122                                  nt_errstr(status),
7123                                  smb_fname_str_dbg(smb_fname_src),
7124                                  smb_fname_str_dbg(smb_fname_dst)));
7125                         break;
7126                 }
7127
7128                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7129                                                               dname);
7130                 if (!smb_fname_dst->original_lcomp) {
7131                         status = NT_STATUS_NO_MEMORY;
7132                         goto out;
7133                 }
7134
7135                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7136                                               attrs, replace_if_exists);
7137
7138                 close_file(req, fsp, NORMAL_CLOSE);
7139
7140                 if (!NT_STATUS_IS_OK(status)) {
7141                         DEBUG(3, ("rename_internals_fsp returned %s for "
7142                                   "rename %s -> %s\n", nt_errstr(status),
7143                                   smb_fname_str_dbg(smb_fname_src),
7144                                   smb_fname_str_dbg(smb_fname_dst)));
7145                         break;
7146                 }
7147
7148                 count++;
7149
7150                 DEBUG(3,("rename_internals: doing rename on %s -> "
7151                          "%s\n", smb_fname_str_dbg(smb_fname_src),
7152                          smb_fname_str_dbg(smb_fname_src)));
7153                 TALLOC_FREE(talloced);
7154         }
7155         TALLOC_FREE(dir_hnd);
7156
7157         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7158                 status = map_nt_error_from_unix(errno);
7159         }
7160
7161  out:
7162         TALLOC_FREE(talloced);
7163         TALLOC_FREE(fname_src_dir);
7164         TALLOC_FREE(fname_src_mask);
7165         return status;
7166 }
7167
7168 /****************************************************************************
7169  Reply to a mv.
7170 ****************************************************************************/
7171
7172 void reply_mv(struct smb_request *req)
7173 {
7174         connection_struct *conn = req->conn;
7175         char *name = NULL;
7176         char *newname = NULL;
7177         const char *p;
7178         uint32_t attrs;
7179         NTSTATUS status;
7180         bool src_has_wcard = False;
7181         bool dest_has_wcard = False;
7182         TALLOC_CTX *ctx = talloc_tos();
7183         struct smb_filename *smb_fname_src = NULL;
7184         struct smb_filename *smb_fname_dst = NULL;
7185         uint32_t src_ucf_flags = (lp_posix_pathnames() ?
7186                 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7187                 UCF_COND_ALLOW_WCARD_LCOMP);
7188         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7189                 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES :
7190                  UCF_COND_ALLOW_WCARD_LCOMP);
7191         bool stream_rename = false;
7192
7193         START_PROFILE(SMBmv);
7194
7195         if (req->wct < 1) {
7196                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7197                 goto out;
7198         }
7199
7200         attrs = SVAL(req->vwv+0, 0);
7201
7202         p = (const char *)req->buf + 1;
7203         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7204                                        &status, &src_has_wcard);
7205         if (!NT_STATUS_IS_OK(status)) {
7206                 reply_nterror(req, status);
7207                 goto out;
7208         }
7209         p++;
7210         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7211                                        &status, &dest_has_wcard);
7212         if (!NT_STATUS_IS_OK(status)) {
7213                 reply_nterror(req, status);
7214                 goto out;
7215         }
7216
7217         if (!lp_posix_pathnames()) {
7218                 /* The newname must begin with a ':' if the
7219                    name contains a ':'. */
7220                 if (strchr_m(name, ':')) {
7221                         if (newname[0] != ':') {
7222                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7223                                 goto out;
7224                         }
7225                         stream_rename = true;
7226                 }
7227         }
7228
7229         status = filename_convert(ctx,
7230                                   conn,
7231                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7232                                   name,
7233                                   src_ucf_flags,
7234                                   &src_has_wcard,
7235                                   &smb_fname_src);
7236
7237         if (!NT_STATUS_IS_OK(status)) {
7238                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7239                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7240                                         ERRSRV, ERRbadpath);
7241                         goto out;
7242                 }
7243                 reply_nterror(req, status);
7244                 goto out;
7245         }
7246
7247         status = filename_convert(ctx,
7248                                   conn,
7249                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7250                                   newname,
7251                                   dst_ucf_flags,
7252                                   &dest_has_wcard,
7253                                   &smb_fname_dst);
7254
7255         if (!NT_STATUS_IS_OK(status)) {
7256                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7257                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7258                                         ERRSRV, ERRbadpath);
7259                         goto out;
7260                 }
7261                 reply_nterror(req, status);
7262                 goto out;
7263         }
7264
7265         if (stream_rename) {
7266                 /* smb_fname_dst->base_name must be the same as
7267                    smb_fname_src->base_name. */
7268                 TALLOC_FREE(smb_fname_dst->base_name);
7269                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7270                                                 smb_fname_src->base_name);
7271                 if (!smb_fname_dst->base_name) {
7272                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7273                         goto out;
7274                 }
7275         }
7276
7277         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7278                  smb_fname_str_dbg(smb_fname_dst)));
7279
7280         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7281                                   attrs, False, src_has_wcard, dest_has_wcard,
7282                                   DELETE_ACCESS);
7283         if (!NT_STATUS_IS_OK(status)) {
7284                 if (open_was_deferred(req->xconn, req->mid)) {
7285                         /* We have re-scheduled this call. */
7286                         goto out;
7287                 }
7288                 reply_nterror(req, status);
7289                 goto out;
7290         }
7291
7292         reply_outbuf(req, 0, 0);
7293  out:
7294         TALLOC_FREE(smb_fname_src);
7295         TALLOC_FREE(smb_fname_dst);
7296         END_PROFILE(SMBmv);
7297         return;
7298 }
7299
7300 /*******************************************************************
7301  Copy a file as part of a reply_copy.
7302 ******************************************************************/
7303
7304 /*
7305  * TODO: check error codes on all callers
7306  */
7307
7308 NTSTATUS copy_file(TALLOC_CTX *ctx,
7309                         connection_struct *conn,
7310                         struct smb_filename *smb_fname_src,
7311                         struct smb_filename *smb_fname_dst,
7312                         int ofun,
7313                         int count,
7314                         bool target_is_directory)
7315 {
7316         struct smb_filename *smb_fname_dst_tmp = NULL;
7317         off_t ret=-1;
7318         files_struct *fsp1,*fsp2;
7319         uint32_t dosattrs;
7320         uint32_t new_create_disposition;
7321         NTSTATUS status;
7322
7323
7324         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7325         if (smb_fname_dst_tmp == NULL) {
7326                 return NT_STATUS_NO_MEMORY;
7327         }
7328
7329         /*
7330          * If the target is a directory, extract the last component from the
7331          * src filename and append it to the dst filename
7332          */
7333         if (target_is_directory) {
7334                 const char *p;
7335
7336                 /* dest/target can't be a stream if it's a directory. */
7337                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7338
7339                 p = strrchr_m(smb_fname_src->base_name,'/');
7340                 if (p) {
7341                         p++;
7342                 } else {
7343                         p = smb_fname_src->base_name;
7344                 }
7345                 smb_fname_dst_tmp->base_name =
7346                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7347                                            p);
7348                 if (!smb_fname_dst_tmp->base_name) {
7349                         status = NT_STATUS_NO_MEMORY;
7350                         goto out;
7351                 }
7352         }
7353
7354         status = vfs_file_exist(conn, smb_fname_src);
7355         if (!NT_STATUS_IS_OK(status)) {
7356                 goto out;
7357         }
7358
7359         if (!target_is_directory && count) {
7360                 new_create_disposition = FILE_OPEN;
7361         } else {
7362                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7363                                                  0, ofun,
7364                                                  NULL, NULL,
7365                                                  &new_create_disposition,
7366                                                  NULL,
7367                                                  NULL)) {
7368                         status = NT_STATUS_INVALID_PARAMETER;
7369                         goto out;
7370                 }
7371         }
7372
7373         /* Open the src file for reading. */
7374         status = SMB_VFS_CREATE_FILE(
7375                 conn,                                   /* conn */
7376                 NULL,                                   /* req */
7377                 0,                                      /* root_dir_fid */
7378                 smb_fname_src,                          /* fname */
7379                 FILE_GENERIC_READ,                      /* access_mask */
7380                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7381                 FILE_OPEN,                              /* create_disposition*/
7382                 0,                                      /* create_options */
7383                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7384                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7385                 NULL,                                   /* lease */
7386                 0,                                      /* allocation_size */
7387                 0,                                      /* private_flags */
7388                 NULL,                                   /* sd */
7389                 NULL,                                   /* ea_list */
7390                 &fsp1,                                  /* result */
7391                 NULL,                                   /* psbuf */
7392                 NULL, NULL);                            /* create context */
7393
7394         if (!NT_STATUS_IS_OK(status)) {
7395                 goto out;
7396         }
7397
7398         dosattrs = dos_mode(conn, smb_fname_src);
7399
7400         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7401                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7402         }
7403
7404         /* Open the dst file for writing. */
7405         status = SMB_VFS_CREATE_FILE(
7406                 conn,                                   /* conn */
7407                 NULL,                                   /* req */
7408                 0,                                      /* root_dir_fid */
7409                 smb_fname_dst,                          /* fname */
7410                 FILE_GENERIC_WRITE,                     /* access_mask */
7411                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7412                 new_create_disposition,                 /* create_disposition*/
7413                 0,                                      /* create_options */
7414                 dosattrs,                               /* file_attributes */
7415                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7416                 NULL,                                   /* lease */
7417                 0,                                      /* allocation_size */
7418                 0,                                      /* private_flags */
7419                 NULL,                                   /* sd */
7420                 NULL,                                   /* ea_list */
7421                 &fsp2,                                  /* result */
7422                 NULL,                                   /* psbuf */
7423                 NULL, NULL);                            /* create context */
7424
7425         if (!NT_STATUS_IS_OK(status)) {
7426                 close_file(NULL, fsp1, ERROR_CLOSE);
7427                 goto out;
7428         }
7429
7430         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7431                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7432                 if (ret == -1) {
7433                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7434                                 strerror(errno)));
7435                         status = map_nt_error_from_unix(errno);
7436                         close_file(NULL, fsp1, ERROR_CLOSE);
7437                         close_file(NULL, fsp2, ERROR_CLOSE);
7438                         goto out;
7439                 }
7440         }
7441
7442         /* Do the actual copy. */
7443         if (smb_fname_src->st.st_ex_size) {
7444                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7445         } else {
7446                 ret = 0;
7447         }
7448
7449         close_file(NULL, fsp1, NORMAL_CLOSE);
7450
7451         /* Ensure the modtime is set correctly on the destination file. */
7452         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7453
7454         /*
7455          * As we are opening fsp1 read-only we only expect
7456          * an error on close on fsp2 if we are out of space.
7457          * Thus we don't look at the error return from the
7458          * close of fsp1.
7459          */
7460         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7461
7462         if (!NT_STATUS_IS_OK(status)) {
7463                 goto out;
7464         }
7465
7466         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7467                 status = NT_STATUS_DISK_FULL;
7468                 goto out;
7469         }
7470
7471         status = NT_STATUS_OK;
7472
7473  out:
7474         TALLOC_FREE(smb_fname_dst_tmp);
7475         return status;
7476 }
7477
7478 /****************************************************************************
7479  Reply to a file copy.
7480 ****************************************************************************/
7481
7482 void reply_copy(struct smb_request *req)
7483 {
7484         connection_struct *conn = req->conn;
7485         struct smb_filename *smb_fname_src = NULL;
7486         struct smb_filename *smb_fname_dst = NULL;
7487         char *fname_src = NULL;
7488         char *fname_dst = NULL;
7489         char *fname_src_mask = NULL;
7490         char *fname_src_dir = NULL;
7491         const char *p;
7492         int count=0;
7493         int error = ERRnoaccess;
7494         int tid2;
7495         int ofun;
7496         int flags;
7497         bool target_is_directory=False;
7498         bool source_has_wild = False;
7499         bool dest_has_wild = False;
7500         NTSTATUS status;
7501         uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7502                 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
7503         uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7504                 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
7505         TALLOC_CTX *ctx = talloc_tos();
7506
7507         START_PROFILE(SMBcopy);
7508
7509         if (req->wct < 3) {
7510                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7511                 goto out;
7512         }
7513
7514         tid2 = SVAL(req->vwv+0, 0);
7515         ofun = SVAL(req->vwv+1, 0);
7516         flags = SVAL(req->vwv+2, 0);
7517
7518         p = (const char *)req->buf;
7519         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7520                                        &status, &source_has_wild);
7521         if (!NT_STATUS_IS_OK(status)) {
7522                 reply_nterror(req, status);
7523                 goto out;
7524         }
7525         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7526                                        &status, &dest_has_wild);
7527         if (!NT_STATUS_IS_OK(status)) {
7528                 reply_nterror(req, status);
7529                 goto out;
7530         }
7531
7532         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7533
7534         if (tid2 != conn->cnum) {
7535                 /* can't currently handle inter share copies XXXX */
7536                 DEBUG(3,("Rejecting inter-share copy\n"));
7537                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7538                 goto out;
7539         }
7540
7541         status = filename_convert(ctx, conn,
7542                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7543                                   fname_src,
7544                                   ucf_flags_src,
7545                                   &source_has_wild,
7546                                   &smb_fname_src);
7547         if (!NT_STATUS_IS_OK(status)) {
7548                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7549                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7550                                         ERRSRV, ERRbadpath);
7551                         goto out;
7552                 }
7553                 reply_nterror(req, status);
7554                 goto out;
7555         }
7556
7557         status = filename_convert(ctx, conn,
7558                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7559                                   fname_dst,
7560                                   ucf_flags_dst,
7561                                   &dest_has_wild,
7562                                   &smb_fname_dst);
7563         if (!NT_STATUS_IS_OK(status)) {
7564                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7565                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7566                                         ERRSRV, ERRbadpath);
7567                         goto out;
7568                 }
7569                 reply_nterror(req, status);
7570                 goto out;
7571         }
7572
7573         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7574
7575         if ((flags&1) && target_is_directory) {
7576                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7577                 goto out;
7578         }
7579
7580         if ((flags&2) && !target_is_directory) {
7581                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7582                 goto out;
7583         }
7584
7585         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7586                 /* wants a tree copy! XXXX */
7587                 DEBUG(3,("Rejecting tree copy\n"));
7588                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7589                 goto out;
7590         }
7591
7592         /* Split up the directory from the filename/mask. */
7593         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7594                                       &fname_src_dir, &fname_src_mask);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7597                 goto out;
7598         }
7599
7600         /*
7601          * We should only check the mangled cache
7602          * here if unix_convert failed. This means
7603          * that the path in 'mask' doesn't exist
7604          * on the file system and so we need to look
7605          * for a possible mangle. This patch from
7606          * Tine Smukavec <valentin.smukavec@hermes.si>.
7607          */
7608         if (!VALID_STAT(smb_fname_src->st) &&
7609             mangle_is_mangled(fname_src_mask, conn->params)) {
7610                 char *new_mask = NULL;
7611                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7612                                             &new_mask, conn->params);
7613
7614                 /* Use demangled name if one was successfully found. */
7615                 if (new_mask) {
7616                         TALLOC_FREE(fname_src_mask);
7617                         fname_src_mask = new_mask;
7618                 }
7619         }
7620
7621         if (!source_has_wild) {
7622
7623                 /*
7624                  * Only one file needs to be copied. Append the mask back onto
7625                  * the directory.
7626                  */
7627                 TALLOC_FREE(smb_fname_src->base_name);
7628                 if (ISDOT(fname_src_dir)) {
7629                         /* Ensure we use canonical names on open. */
7630                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7631                                                         "%s",
7632                                                         fname_src_mask);
7633                 } else {
7634                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7635                                                         "%s/%s",
7636                                                         fname_src_dir,
7637                                                         fname_src_mask);
7638                 }
7639                 if (!smb_fname_src->base_name) {
7640                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7641                         goto out;
7642                 }
7643
7644                 if (dest_has_wild) {
7645                         char *fname_dst_mod = NULL;
7646                         if (!resolve_wildcards(smb_fname_dst,
7647                                                smb_fname_src->base_name,
7648                                                smb_fname_dst->base_name,
7649                                                &fname_dst_mod)) {
7650                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7651                                 goto out;
7652                         }
7653                         TALLOC_FREE(smb_fname_dst->base_name);
7654                         smb_fname_dst->base_name = fname_dst_mod;
7655                 }
7656
7657                 status = check_name(conn, smb_fname_src->base_name);
7658                 if (!NT_STATUS_IS_OK(status)) {
7659                         reply_nterror(req, status);
7660                         goto out;
7661                 }
7662
7663                 status = check_name(conn, smb_fname_dst->base_name);
7664                 if (!NT_STATUS_IS_OK(status)) {
7665                         reply_nterror(req, status);
7666                         goto out;
7667                 }
7668
7669                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7670                                    ofun, count, target_is_directory);
7671
7672                 if(!NT_STATUS_IS_OK(status)) {
7673                         reply_nterror(req, status);
7674                         goto out;
7675                 } else {
7676                         count++;
7677                 }
7678         } else {
7679                 struct smb_Dir *dir_hnd = NULL;
7680                 const char *dname = NULL;
7681                 char *talloced = NULL;
7682                 long offset = 0;
7683
7684                 /*
7685                  * There is a wildcard that requires us to actually read the
7686                  * src dir and copy each file matching the mask to the dst.
7687                  * Right now streams won't be copied, but this could
7688                  * presumably be added with a nested loop for reach dir entry.
7689                  */
7690                 SMB_ASSERT(!smb_fname_src->stream_name);
7691                 SMB_ASSERT(!smb_fname_dst->stream_name);
7692
7693                 smb_fname_src->stream_name = NULL;
7694                 smb_fname_dst->stream_name = NULL;
7695
7696                 if (strequal(fname_src_mask,"????????.???")) {
7697                         TALLOC_FREE(fname_src_mask);
7698                         fname_src_mask = talloc_strdup(ctx, "*");
7699                         if (!fname_src_mask) {
7700                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7701                                 goto out;
7702                         }
7703                 }
7704
7705                 status = check_name(conn, fname_src_dir);
7706                 if (!NT_STATUS_IS_OK(status)) {
7707                         reply_nterror(req, status);
7708                         goto out;
7709                 }
7710
7711                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7712                 if (dir_hnd == NULL) {
7713                         status = map_nt_error_from_unix(errno);
7714                         reply_nterror(req, status);
7715                         goto out;
7716                 }
7717
7718                 error = ERRbadfile;
7719
7720                 /* Iterate over the src dir copying each entry to the dst. */
7721                 while ((dname = ReadDirName(dir_hnd, &offset,
7722                                             &smb_fname_src->st, &talloced))) {
7723                         char *destname = NULL;
7724
7725                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7726                                 TALLOC_FREE(talloced);
7727                                 continue;
7728                         }
7729
7730                         if (!is_visible_file(conn, fname_src_dir, dname,
7731                                              &smb_fname_src->st, false)) {
7732                                 TALLOC_FREE(talloced);
7733                                 continue;
7734                         }
7735
7736                         if(!mask_match(dname, fname_src_mask,
7737                                        conn->case_sensitive)) {
7738                                 TALLOC_FREE(talloced);
7739                                 continue;
7740                         }
7741
7742                         error = ERRnoaccess;
7743
7744                         /* Get the src smb_fname struct setup. */
7745                         TALLOC_FREE(smb_fname_src->base_name);
7746                         if (ISDOT(fname_src_dir)) {
7747                                 /* Ensure we use canonical names on open. */
7748                                 smb_fname_src->base_name =
7749                                         talloc_asprintf(smb_fname_src, "%s",
7750                                                 dname);
7751                         } else {
7752                                 smb_fname_src->base_name =
7753                                         talloc_asprintf(smb_fname_src, "%s/%s",
7754                                                 fname_src_dir, dname);
7755                         }
7756
7757                         if (!smb_fname_src->base_name) {
7758                                 TALLOC_FREE(dir_hnd);
7759                                 TALLOC_FREE(talloced);
7760                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7761                                 goto out;
7762                         }
7763
7764                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7765                                                smb_fname_dst->base_name,
7766                                                &destname)) {
7767                                 TALLOC_FREE(talloced);
7768                                 continue;
7769                         }
7770                         if (!destname) {
7771                                 TALLOC_FREE(dir_hnd);
7772                                 TALLOC_FREE(talloced);
7773                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7774                                 goto out;
7775                         }
7776
7777                         TALLOC_FREE(smb_fname_dst->base_name);
7778                         smb_fname_dst->base_name = destname;
7779
7780                         status = check_name(conn, smb_fname_src->base_name);
7781                         if (!NT_STATUS_IS_OK(status)) {
7782                                 TALLOC_FREE(dir_hnd);
7783                                 TALLOC_FREE(talloced);
7784                                 reply_nterror(req, status);
7785                                 goto out;
7786                         }
7787
7788                         status = check_name(conn, smb_fname_dst->base_name);
7789                         if (!NT_STATUS_IS_OK(status)) {
7790                                 TALLOC_FREE(dir_hnd);
7791                                 TALLOC_FREE(talloced);
7792                                 reply_nterror(req, status);
7793                                 goto out;
7794                         }
7795
7796                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7797                                 smb_fname_src->base_name,
7798                                 smb_fname_dst->base_name));
7799
7800                         status = copy_file(ctx, conn, smb_fname_src,
7801                                            smb_fname_dst, ofun, count,
7802                                            target_is_directory);
7803                         if (NT_STATUS_IS_OK(status)) {
7804                                 count++;
7805                         }
7806
7807                         TALLOC_FREE(talloced);
7808                 }
7809                 TALLOC_FREE(dir_hnd);
7810         }
7811
7812         if (count == 0) {
7813                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7814                 goto out;
7815         }
7816
7817         reply_outbuf(req, 1, 0);
7818         SSVAL(req->outbuf,smb_vwv0,count);
7819  out:
7820         TALLOC_FREE(smb_fname_src);
7821         TALLOC_FREE(smb_fname_dst);
7822         TALLOC_FREE(fname_src);
7823         TALLOC_FREE(fname_dst);
7824         TALLOC_FREE(fname_src_mask);
7825         TALLOC_FREE(fname_src_dir);
7826
7827         END_PROFILE(SMBcopy);
7828         return;
7829 }
7830
7831 #undef DBGC_CLASS
7832 #define DBGC_CLASS DBGC_LOCKING
7833
7834 /****************************************************************************
7835  Get a lock pid, dealing with large count requests.
7836 ****************************************************************************/
7837
7838 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7839                     bool large_file_format)
7840 {
7841         if(!large_file_format)
7842                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7843         else
7844                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7845 }
7846
7847 /****************************************************************************
7848  Get a lock count, dealing with large count requests.
7849 ****************************************************************************/
7850
7851 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7852                         bool large_file_format)
7853 {
7854         uint64_t count = 0;
7855
7856         if(!large_file_format) {
7857                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7858         } else {
7859                 /*
7860                  * No BVAL, this is reversed!
7861                  */
7862                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7863                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7864         }
7865
7866         return count;
7867 }
7868
7869 /****************************************************************************
7870  Get a lock offset, dealing with large offset requests.
7871 ****************************************************************************/
7872
7873 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7874                          bool large_file_format)
7875 {
7876         uint64_t offset = 0;
7877
7878         if(!large_file_format) {
7879                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7880         } else {
7881                 /*
7882                  * No BVAL, this is reversed!
7883                  */
7884                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7885                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7886         }
7887
7888         return offset;
7889 }
7890
7891 NTSTATUS smbd_do_locking(struct smb_request *req,
7892                          files_struct *fsp,
7893                          uint8_t type,
7894                          int32_t timeout,
7895                          uint16_t num_locks,
7896                          struct smbd_lock_element *locks,
7897                          bool *async)
7898 {
7899         connection_struct *conn = req->conn;
7900         int i;
7901         NTSTATUS status = NT_STATUS_OK;
7902
7903         *async = false;
7904
7905         /* Setup the timeout in seconds. */
7906
7907         if (!lp_blocking_locks(SNUM(conn))) {
7908                 timeout = 0;
7909         }
7910
7911         for(i = 0; i < (int)num_locks; i++) {
7912                 struct smbd_lock_element *e = &locks[i];
7913
7914                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7915                           "%llu, file %s timeout = %d\n",
7916                           (double)e->offset,
7917                           (double)e->count,
7918                           (unsigned long long)e->smblctx,
7919                           fsp_str_dbg(fsp),
7920                           (int)timeout));
7921
7922                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7923                         struct blocking_lock_record *blr = NULL;
7924
7925                         if (num_locks > 1) {
7926                                 /*
7927                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7928                                  * if the lock vector contains one entry. When given multiple cancel
7929                                  * requests in a single PDU we expect the server to return an
7930                                  * error. Windows servers seem to accept the request but only
7931                                  * cancel the first lock.
7932                                  * JRA - Do what Windows does (tm) :-).
7933                                  */
7934
7935 #if 0
7936                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7937                                 return NT_STATUS_DOS(ERRDOS,
7938                                                 ERRcancelviolation);
7939 #else
7940                                 /* Windows behavior. */
7941                                 if (i != 0) {
7942                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7943                                                 "cancel request\n"));
7944                                         continue;
7945                                 }
7946 #endif
7947                         }
7948
7949                         if (lp_blocking_locks(SNUM(conn))) {
7950
7951                                 /* Schedule a message to ourselves to
7952                                    remove the blocking lock record and
7953                                    return the right error. */
7954
7955                                 blr = blocking_lock_cancel_smb1(fsp,
7956                                                 e->smblctx,
7957                                                 e->offset,
7958                                                 e->count,
7959                                                 WINDOWS_LOCK,
7960                                                 type,
7961                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7962                                 if (blr == NULL) {
7963                                         return NT_STATUS_DOS(
7964                                                         ERRDOS,
7965                                                         ERRcancelviolation);
7966                                 }
7967                         }
7968                         /* Remove a matching pending lock. */
7969                         status = do_lock_cancel(fsp,
7970                                                 e->smblctx,
7971                                                 e->count,
7972                                                 e->offset,
7973                                                 WINDOWS_LOCK);
7974                 } else {
7975                         bool blocking_lock = timeout ? true : false;
7976                         bool defer_lock = false;
7977                         struct byte_range_lock *br_lck;
7978                         uint64_t block_smblctx;
7979
7980                         br_lck = do_lock(req->sconn->msg_ctx,
7981                                         fsp,
7982                                         e->smblctx,
7983                                         e->count,
7984                                         e->offset, 
7985                                         e->brltype,
7986                                         WINDOWS_LOCK,
7987                                         blocking_lock,
7988                                         &status,
7989                                         &block_smblctx);
7990
7991                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7992                                 /* Windows internal resolution for blocking locks seems
7993                                    to be about 200ms... Don't wait for less than that. JRA. */
7994                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7995                                         timeout = lp_lock_spin_time();
7996                                 }
7997                                 defer_lock = true;
7998                         }
7999
8000                         /* If a lock sent with timeout of zero would fail, and
8001                          * this lock has been requested multiple times,
8002                          * according to brl_lock_failed() we convert this
8003                          * request to a blocking lock with a timeout of between
8004                          * 150 - 300 milliseconds.
8005                          *
8006                          * If lp_lock_spin_time() has been set to 0, we skip
8007                          * this blocking retry and fail immediately.
8008                          *
8009                          * Replacement for do_lock_spin(). JRA. */
8010
8011                         if (!req->sconn->using_smb2 &&
8012                             br_lck && lp_blocking_locks(SNUM(conn)) &&
8013                             lp_lock_spin_time() && !blocking_lock &&
8014                             NT_STATUS_EQUAL((status),
8015                                 NT_STATUS_FILE_LOCK_CONFLICT))
8016                         {
8017                                 defer_lock = true;
8018                                 timeout = lp_lock_spin_time();
8019                         }
8020
8021                         if (br_lck && defer_lock) {
8022                                 /*
8023                                  * A blocking lock was requested. Package up
8024                                  * this smb into a queued request and push it
8025                                  * onto the blocking lock queue.
8026                                  */
8027                                 if(push_blocking_lock_request(br_lck,
8028                                                         req,
8029                                                         fsp,
8030                                                         timeout,
8031                                                         i,
8032                                                         e->smblctx,
8033                                                         e->brltype,
8034                                                         WINDOWS_LOCK,
8035                                                         e->offset,
8036                                                         e->count,
8037                                                         block_smblctx)) {
8038                                         TALLOC_FREE(br_lck);
8039                                         *async = true;
8040                                         return NT_STATUS_OK;
8041                                 }
8042                         }
8043
8044                         TALLOC_FREE(br_lck);
8045                 }
8046
8047                 if (!NT_STATUS_IS_OK(status)) {
8048                         break;
8049                 }
8050         }
8051
8052         /* If any of the above locks failed, then we must unlock
8053            all of the previous locks (X/Open spec). */
8054
8055         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8056
8057                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8058                         i = -1; /* we want to skip the for loop */
8059                 }
8060
8061                 /*
8062                  * Ensure we don't do a remove on the lock that just failed,
8063                  * as under POSIX rules, if we have a lock already there, we
8064                  * will delete it (and we shouldn't) .....
8065                  */
8066                 for(i--; i >= 0; i--) {
8067                         struct smbd_lock_element *e = &locks[i];
8068
8069                         do_unlock(req->sconn->msg_ctx,
8070                                 fsp,
8071                                 e->smblctx,
8072                                 e->count,
8073                                 e->offset,
8074                                 WINDOWS_LOCK);
8075                 }
8076                 return status;
8077         }
8078
8079         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8080                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8081
8082         return NT_STATUS_OK;
8083 }
8084
8085 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8086                            files_struct *fsp,
8087                            uint16_t num_ulocks,
8088                            struct smbd_lock_element *ulocks)
8089 {
8090         int i;
8091
8092         for(i = 0; i < (int)num_ulocks; i++) {
8093                 struct smbd_lock_element *e = &ulocks[i];
8094                 NTSTATUS status;
8095
8096                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8097                           "pid %u, file %s\n", __func__,
8098                           (double)e->offset,
8099                           (double)e->count,
8100                           (unsigned int)e->smblctx,
8101                           fsp_str_dbg(fsp)));
8102
8103                 if (e->brltype != UNLOCK_LOCK) {
8104                         /* this can only happen with SMB2 */
8105                         return NT_STATUS_INVALID_PARAMETER;
8106                 }
8107
8108                 status = do_unlock(req->sconn->msg_ctx,
8109                                 fsp,
8110                                 e->smblctx,
8111                                 e->count,
8112                                 e->offset,
8113                                 WINDOWS_LOCK);
8114
8115                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8116                            nt_errstr(status)));
8117
8118                 if (!NT_STATUS_IS_OK(status)) {
8119                         return status;
8120                 }
8121         }
8122
8123         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8124                   num_ulocks));
8125
8126         return NT_STATUS_OK;
8127 }
8128
8129 /****************************************************************************
8130  Reply to a lockingX request.
8131 ****************************************************************************/
8132
8133 void reply_lockingX(struct smb_request *req)
8134 {
8135         connection_struct *conn = req->conn;
8136         files_struct *fsp;
8137         unsigned char locktype;
8138         unsigned char oplocklevel;
8139         uint16_t num_ulocks;
8140         uint16_t num_locks;
8141         int32_t lock_timeout;
8142         int i;
8143         const uint8_t *data;
8144         bool large_file_format;
8145         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8146         struct smbd_lock_element *ulocks;
8147         struct smbd_lock_element *locks;
8148         bool async = false;
8149
8150         START_PROFILE(SMBlockingX);
8151
8152         if (req->wct < 8) {
8153                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8154                 END_PROFILE(SMBlockingX);
8155                 return;
8156         }
8157
8158         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8159         locktype = CVAL(req->vwv+3, 0);
8160         oplocklevel = CVAL(req->vwv+3, 1);
8161         num_ulocks = SVAL(req->vwv+6, 0);
8162         num_locks = SVAL(req->vwv+7, 0);
8163         lock_timeout = IVAL(req->vwv+4, 0);
8164         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8165
8166         if (!check_fsp(conn, req, fsp)) {
8167                 END_PROFILE(SMBlockingX);
8168                 return;
8169         }
8170
8171         data = req->buf;
8172
8173         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8174                 /* we don't support these - and CANCEL_LOCK makes w2k
8175                    and XP reboot so I don't really want to be
8176                    compatible! (tridge) */
8177                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8178                 END_PROFILE(SMBlockingX);
8179                 return;
8180         }
8181
8182         /* Check if this is an oplock break on a file
8183            we have granted an oplock on.
8184         */
8185         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8186                 /* Client can insist on breaking to none. */
8187                 bool break_to_none = (oplocklevel == 0);
8188                 bool result;
8189
8190                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8191                          "for %s\n", (unsigned int)oplocklevel,
8192                          fsp_fnum_dbg(fsp)));
8193
8194                 /*
8195                  * Make sure we have granted an exclusive or batch oplock on
8196                  * this file.
8197                  */
8198
8199                 if (fsp->oplock_type == 0) {
8200
8201                         /* The Samba4 nbench simulator doesn't understand
8202                            the difference between break to level2 and break
8203                            to none from level2 - it sends oplock break
8204                            replies in both cases. Don't keep logging an error
8205                            message here - just ignore it. JRA. */
8206
8207                         DEBUG(5,("reply_lockingX: Error : oplock break from "
8208                                  "client for %s (oplock=%d) and no "
8209                                  "oplock granted on this file (%s).\n",
8210                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
8211                                  fsp_str_dbg(fsp)));
8212
8213                         /* if this is a pure oplock break request then don't
8214                          * send a reply */
8215                         if (num_locks == 0 && num_ulocks == 0) {
8216                                 END_PROFILE(SMBlockingX);
8217                                 return;
8218                         } else {
8219                                 END_PROFILE(SMBlockingX);
8220                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8221                                 return;
8222                         }
8223                 }
8224
8225                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8226                     (break_to_none)) {
8227                         result = remove_oplock(fsp);
8228                 } else {
8229                         result = downgrade_oplock(fsp);
8230                 }
8231
8232                 if (!result) {
8233                         DEBUG(0, ("reply_lockingX: error in removing "
8234                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
8235                         /* Hmmm. Is this panic justified? */
8236                         smb_panic("internal tdb error");
8237                 }
8238
8239                 /* if this is a pure oplock break request then don't send a
8240                  * reply */
8241                 if (num_locks == 0 && num_ulocks == 0) {
8242                         /* Sanity check - ensure a pure oplock break is not a
8243                            chained request. */
8244                         if (CVAL(req->vwv+0, 0) != 0xff) {
8245                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8246                                          "break is a chained %d request !\n",
8247                                          (unsigned int)CVAL(req->vwv+0, 0)));
8248                         }
8249                         END_PROFILE(SMBlockingX);
8250                         return;
8251                 }
8252         }
8253
8254         if (req->buflen <
8255             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8256                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257                 END_PROFILE(SMBlockingX);
8258                 return;
8259         }
8260
8261         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8262         if (ulocks == NULL) {
8263                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8264                 END_PROFILE(SMBlockingX);
8265                 return;
8266         }
8267
8268         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8269         if (locks == NULL) {
8270                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8271                 END_PROFILE(SMBlockingX);
8272                 return;
8273         }
8274
8275         /* Data now points at the beginning of the list
8276            of smb_unlkrng structs */
8277         for(i = 0; i < (int)num_ulocks; i++) {
8278                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8279                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8280                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8281                 ulocks[i].brltype = UNLOCK_LOCK;
8282         }
8283
8284         /* Now do any requested locks */
8285         data += ((large_file_format ? 20 : 10)*num_ulocks);
8286
8287         /* Data now points at the beginning of the list
8288            of smb_lkrng structs */
8289
8290         for(i = 0; i < (int)num_locks; i++) {
8291                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8292                 locks[i].count = get_lock_count(data, i, large_file_format);
8293                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8294
8295                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8296                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8297                                 locks[i].brltype = PENDING_READ_LOCK;
8298                         } else {
8299                                 locks[i].brltype = READ_LOCK;
8300                         }
8301                 } else {
8302                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8303                                 locks[i].brltype = PENDING_WRITE_LOCK;
8304                         } else {
8305                                 locks[i].brltype = WRITE_LOCK;
8306                         }
8307                 }
8308         }
8309
8310         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8311         if (!NT_STATUS_IS_OK(status)) {
8312                 END_PROFILE(SMBlockingX);
8313                 reply_nterror(req, status);
8314                 return;
8315         }
8316
8317         status = smbd_do_locking(req, fsp,
8318                                  locktype, lock_timeout,
8319                                  num_locks, locks,
8320                                  &async);
8321         if (!NT_STATUS_IS_OK(status)) {
8322                 END_PROFILE(SMBlockingX);
8323                 reply_nterror(req, status);
8324                 return;
8325         }
8326         if (async) {
8327                 END_PROFILE(SMBlockingX);
8328                 return;
8329         }
8330
8331         reply_outbuf(req, 2, 0);
8332         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8333         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8334
8335         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8336                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8337
8338         END_PROFILE(SMBlockingX);
8339 }
8340
8341 #undef DBGC_CLASS
8342 #define DBGC_CLASS DBGC_ALL
8343
8344 /****************************************************************************
8345  Reply to a SMBreadbmpx (read block multiplex) request.
8346  Always reply with an error, if someone has a platform really needs this,
8347  please contact vl@samba.org
8348 ****************************************************************************/
8349
8350 void reply_readbmpx(struct smb_request *req)
8351 {
8352         START_PROFILE(SMBreadBmpx);
8353         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8354         END_PROFILE(SMBreadBmpx);
8355         return;
8356 }
8357
8358 /****************************************************************************
8359  Reply to a SMBreadbs (read block multiplex secondary) request.
8360  Always reply with an error, if someone has a platform really needs this,
8361  please contact vl@samba.org
8362 ****************************************************************************/
8363
8364 void reply_readbs(struct smb_request *req)
8365 {
8366         START_PROFILE(SMBreadBs);
8367         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8368         END_PROFILE(SMBreadBs);
8369         return;
8370 }
8371
8372 /****************************************************************************
8373  Reply to a SMBsetattrE.
8374 ****************************************************************************/
8375
8376 void reply_setattrE(struct smb_request *req)
8377 {
8378         connection_struct *conn = req->conn;
8379         struct smb_file_time ft;
8380         files_struct *fsp;
8381         NTSTATUS status;
8382
8383         START_PROFILE(SMBsetattrE);
8384         ZERO_STRUCT(ft);
8385
8386         if (req->wct < 7) {
8387                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8388                 goto out;
8389         }
8390
8391         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8392
8393         if(!fsp || (fsp->conn != conn)) {
8394                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8395                 goto out;
8396         }
8397
8398         /*
8399          * Convert the DOS times into unix times.
8400          */
8401
8402         ft.atime = convert_time_t_to_timespec(
8403             srv_make_unix_date2(req->vwv+3));
8404         ft.mtime = convert_time_t_to_timespec(
8405             srv_make_unix_date2(req->vwv+5));
8406         ft.create_time = convert_time_t_to_timespec(
8407             srv_make_unix_date2(req->vwv+1));
8408
8409         reply_outbuf(req, 0, 0);
8410
8411         /* 
8412          * Patch from Ray Frush <frush@engr.colostate.edu>
8413          * Sometimes times are sent as zero - ignore them.
8414          */
8415
8416         /* Ensure we have a valid stat struct for the source. */
8417         status = vfs_stat_fsp(fsp);
8418         if (!NT_STATUS_IS_OK(status)) {
8419                 reply_nterror(req, status);
8420                 goto out;
8421         }
8422
8423         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8424                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8425                 goto out;
8426         }
8427
8428         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8429         if (!NT_STATUS_IS_OK(status)) {
8430                 reply_nterror(req, status);
8431                 goto out;
8432         }
8433
8434         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8435                " createtime=%u\n",
8436                 fsp_fnum_dbg(fsp),
8437                 (unsigned int)ft.atime.tv_sec,
8438                 (unsigned int)ft.mtime.tv_sec,
8439                 (unsigned int)ft.create_time.tv_sec
8440                 ));
8441  out:
8442         END_PROFILE(SMBsetattrE);
8443         return;
8444 }
8445
8446
8447 /* Back from the dead for OS/2..... JRA. */
8448
8449 /****************************************************************************
8450  Reply to a SMBwritebmpx (write block multiplex primary) request.
8451  Always reply with an error, if someone has a platform really needs this,
8452  please contact vl@samba.org
8453 ****************************************************************************/
8454
8455 void reply_writebmpx(struct smb_request *req)
8456 {
8457         START_PROFILE(SMBwriteBmpx);
8458         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8459         END_PROFILE(SMBwriteBmpx);
8460         return;
8461 }
8462
8463 /****************************************************************************
8464  Reply to a SMBwritebs (write block multiplex secondary) request.
8465  Always reply with an error, if someone has a platform really needs this,
8466  please contact vl@samba.org
8467 ****************************************************************************/
8468
8469 void reply_writebs(struct smb_request *req)
8470 {
8471         START_PROFILE(SMBwriteBs);
8472         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8473         END_PROFILE(SMBwriteBs);
8474         return;
8475 }
8476
8477 /****************************************************************************
8478  Reply to a SMBgetattrE.
8479 ****************************************************************************/
8480
8481 void reply_getattrE(struct smb_request *req)
8482 {
8483         connection_struct *conn = req->conn;
8484         int mode;
8485         files_struct *fsp;
8486         struct timespec create_ts;
8487
8488         START_PROFILE(SMBgetattrE);
8489
8490         if (req->wct < 1) {
8491                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8492                 END_PROFILE(SMBgetattrE);
8493                 return;
8494         }
8495
8496         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8497
8498         if(!fsp || (fsp->conn != conn)) {
8499                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8500                 END_PROFILE(SMBgetattrE);
8501                 return;
8502         }
8503
8504         /* Do an fstat on this file */
8505         if(fsp_stat(fsp)) {
8506                 reply_nterror(req, map_nt_error_from_unix(errno));
8507                 END_PROFILE(SMBgetattrE);
8508                 return;
8509         }
8510
8511         mode = dos_mode(conn, fsp->fsp_name);
8512
8513         /*
8514          * Convert the times into dos times. Set create
8515          * date to be last modify date as UNIX doesn't save
8516          * this.
8517          */
8518
8519         reply_outbuf(req, 11, 0);
8520
8521         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8522         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8523         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8524                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8525         /* Should we check pending modtime here ? JRA */
8526         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8527                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8528
8529         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8530                 SIVAL(req->outbuf, smb_vwv6, 0);
8531                 SIVAL(req->outbuf, smb_vwv8, 0);
8532         } else {
8533                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8534                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8535                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8536         }
8537         SSVAL(req->outbuf,smb_vwv10, mode);
8538
8539         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8540
8541         END_PROFILE(SMBgetattrE);
8542         return;
8543 }