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