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