s3:smbd: pass smbXsrv_connection to smbd_[un]lock_socket()
[nivanova/samba-autobuild/.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #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 smbXsrv_connection *xconn = req->xconn;
697         struct smbd_server_connection *sconn = xconn->sconn;
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 smbXsrv_connection *xconn = req->xconn;
775         struct smbd_server_connection *sconn = xconn->sconn;
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(xconn,
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 smbXsrv_connection *xconn = req->xconn;
1559         struct smbd_server_connection *sconn = xconn->sconn;
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(struct smbXsrv_connection *xconn, files_struct *fsp,
3030                       off_t startpos, size_t nread)
3031 {
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). Returns 0 on success
3092 ****************************************************************************/
3093
3094 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3095                             files_struct *fsp,
3096                             ssize_t nread,
3097                             size_t headersize,
3098                             size_t smb_maxcnt)
3099 {
3100 #define SHORT_SEND_BUFSIZE 1024
3101         if (nread < headersize) {
3102                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3103                         "header for file %s (%s). Terminating\n",
3104                         fsp_str_dbg(fsp), strerror(errno)));
3105                 return -1;
3106         }
3107
3108         nread -= headersize;
3109
3110         if (nread < smb_maxcnt) {
3111                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3112                 if (!buf) {
3113                         DEBUG(0,("sendfile_short_send: malloc failed "
3114                                 "for file %s (%s). Terminating\n",
3115                                 fsp_str_dbg(fsp), strerror(errno)));
3116                         return -1;
3117                 }
3118
3119                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3120                         "with zeros !\n", fsp_str_dbg(fsp)));
3121
3122                 while (nread < smb_maxcnt) {
3123                         /*
3124                          * We asked for the real file size and told sendfile
3125                          * to not go beyond the end of the file. But it can
3126                          * happen that in between our fstat call and the
3127                          * sendfile call the file was truncated. This is very
3128                          * bad because we have already announced the larger
3129                          * number of bytes to the client.
3130                          *
3131                          * The best we can do now is to send 0-bytes, just as
3132                          * a read from a hole in a sparse file would do.
3133                          *
3134                          * This should happen rarely enough that I don't care
3135                          * about efficiency here :-)
3136                          */
3137                         size_t to_write;
3138                         ssize_t ret;
3139
3140                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3141                         ret = write_data(xconn->transport.sock, buf, to_write);
3142                         if (ret != to_write) {
3143                                 int saved_errno = errno;
3144                                 /*
3145                                  * Try and give an error message saying what
3146                                  * client failed.
3147                                  */
3148                                 DEBUG(0, ("write_data failed for client %s. "
3149                                           "Error %s\n",
3150                                           smbXsrv_connection_dbg(xconn),
3151                                           strerror(saved_errno)));
3152                                 errno = saved_errno;
3153                                 return -1;
3154                         }
3155                         nread += to_write;
3156                 }
3157                 SAFE_FREE(buf);
3158         }
3159
3160         return 0;
3161 }
3162
3163 /****************************************************************************
3164  Return a readbraw error (4 bytes of zero).
3165 ****************************************************************************/
3166
3167 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3168 {
3169         char header[4];
3170
3171         SIVAL(header,0,0);
3172
3173         smbd_lock_socket(xconn);
3174         if (write_data(xconn->transport.sock,header,4) != 4) {
3175                 int saved_errno = errno;
3176                 /*
3177                  * Try and give an error message saying what
3178                  * client failed.
3179                  */
3180                 DEBUG(0, ("write_data failed for client %s. "
3181                           "Error %s\n",
3182                           smbXsrv_connection_dbg(xconn),
3183                           strerror(saved_errno)));
3184                 errno = saved_errno;
3185
3186                 fail_readraw();
3187         }
3188         smbd_unlock_socket(xconn);
3189 }
3190
3191 /****************************************************************************
3192  Use sendfile in readbraw.
3193 ****************************************************************************/
3194
3195 static void send_file_readbraw(connection_struct *conn,
3196                                struct smb_request *req,
3197                                files_struct *fsp,
3198                                off_t startpos,
3199                                size_t nread,
3200                                ssize_t mincount)
3201 {
3202         struct smbXsrv_connection *xconn = req->xconn;
3203         char *outbuf = NULL;
3204         ssize_t ret=0;
3205
3206         /*
3207          * We can only use sendfile on a non-chained packet 
3208          * but we can use on a non-oplocked file. tridge proved this
3209          * on a train in Germany :-). JRA.
3210          * reply_readbraw has already checked the length.
3211          */
3212
3213         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3214             (fsp->wcp == NULL) &&
3215             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3216                 ssize_t sendfile_read = -1;
3217                 char header[4];
3218                 DATA_BLOB header_blob;
3219
3220                 _smb_setlen(header,nread);
3221                 header_blob = data_blob_const(header, 4);
3222
3223                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3224                                                  &header_blob, startpos,
3225                                                  nread);
3226                 if (sendfile_read == -1) {
3227                         /* Returning ENOSYS means no data at all was sent.
3228                          * Do this as a normal read. */
3229                         if (errno == ENOSYS) {
3230                                 goto normal_readbraw;
3231                         }
3232
3233                         /*
3234                          * Special hack for broken Linux with no working sendfile. If we
3235                          * return EINTR we sent the header but not the rest of the data.
3236                          * Fake this up by doing read/write calls.
3237                          */
3238                         if (errno == EINTR) {
3239                                 /* Ensure we don't do this again. */
3240                                 set_use_sendfile(SNUM(conn), False);
3241                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242
3243                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3244                                         DEBUG(0,("send_file_readbraw: "
3245                                                  "fake_sendfile failed for "
3246                                                  "file %s (%s).\n",
3247                                                  fsp_str_dbg(fsp),
3248                                                  strerror(errno)));
3249                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3250                                 }
3251                                 return;
3252                         }
3253
3254                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3255                                  "file %s (%s). Terminating\n",
3256                                  fsp_str_dbg(fsp), strerror(errno)));
3257                         exit_server_cleanly("send_file_readbraw sendfile failed");
3258                 } else if (sendfile_read == 0) {
3259                         /*
3260                          * Some sendfile implementations return 0 to indicate
3261                          * that there was a short read, but nothing was
3262                          * actually written to the socket.  In this case,
3263                          * fallback to the normal read path so the header gets
3264                          * the correct byte count.
3265                          */
3266                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3267                                   "bytes falling back to the normal read: "
3268                                   "%s\n", fsp_str_dbg(fsp)));
3269                         goto normal_readbraw;
3270                 }
3271
3272                 /* Deal with possible short send. */
3273                 if (sendfile_read != 4+nread) {
3274                         ret = sendfile_short_send(xconn, fsp,
3275                                                   sendfile_read, 4, nread);
3276                         if (ret == -1) {
3277                                 fail_readraw();
3278                         }
3279                 }
3280                 return;
3281         }
3282
3283 normal_readbraw:
3284
3285         outbuf = talloc_array(NULL, char, nread+4);
3286         if (!outbuf) {
3287                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3288                         (unsigned)(nread+4)));
3289                 reply_readbraw_error(xconn);
3290                 return;
3291         }
3292
3293         if (nread > 0) {
3294                 ret = read_file(fsp,outbuf+4,startpos,nread);
3295 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3296                 if (ret < mincount)
3297                         ret = 0;
3298 #else
3299                 if (ret < nread)
3300                         ret = 0;
3301 #endif
3302         }
3303
3304         _smb_setlen(outbuf,ret);
3305         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3306                 int saved_errno = errno;
3307                 /*
3308                  * Try and give an error message saying what
3309                  * client failed.
3310                  */
3311                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3312                           smbXsrv_connection_dbg(xconn),
3313                           strerror(saved_errno)));
3314                 errno = saved_errno;
3315
3316                 fail_readraw();
3317         }
3318
3319         TALLOC_FREE(outbuf);
3320 }
3321
3322 /****************************************************************************
3323  Reply to a readbraw (core+ protocol).
3324 ****************************************************************************/
3325
3326 void reply_readbraw(struct smb_request *req)
3327 {
3328         connection_struct *conn = req->conn;
3329         struct smbXsrv_connection *xconn = req->xconn;
3330         ssize_t maxcount,mincount;
3331         size_t nread = 0;
3332         off_t startpos;
3333         files_struct *fsp;
3334         struct lock_struct lock;
3335         off_t size = 0;
3336
3337         START_PROFILE(SMBreadbraw);
3338
3339         if (srv_is_signing_active(xconn) || req->encrypted) {
3340                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3341                         "raw reads/writes are disallowed.");
3342         }
3343
3344         if (req->wct < 8) {
3345                 reply_readbraw_error(xconn);
3346                 END_PROFILE(SMBreadbraw);
3347                 return;
3348         }
3349
3350         if (xconn->smb1.echo_handler.trusted_fde) {
3351                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3352                          "'async smb echo handler = yes'\n"));
3353                 reply_readbraw_error(xconn);
3354                 END_PROFILE(SMBreadbraw);
3355                 return;
3356         }
3357
3358         /*
3359          * Special check if an oplock break has been issued
3360          * and the readraw request croses on the wire, we must
3361          * return a zero length response here.
3362          */
3363
3364         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3365
3366         /*
3367          * We have to do a check_fsp by hand here, as
3368          * we must always return 4 zero bytes on error,
3369          * not a NTSTATUS.
3370          */
3371
3372         if (!fsp || !conn || conn != fsp->conn ||
3373                         req->vuid != fsp->vuid ||
3374                         fsp->is_directory || fsp->fh->fd == -1) {
3375                 /*
3376                  * fsp could be NULL here so use the value from the packet. JRA.
3377                  */
3378                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3379                         "- cache prime?\n",
3380                         (int)SVAL(req->vwv+0, 0)));
3381                 reply_readbraw_error(xconn);
3382                 END_PROFILE(SMBreadbraw);
3383                 return;
3384         }
3385
3386         /* Do a "by hand" version of CHECK_READ. */
3387         if (!(fsp->can_read ||
3388                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3389                                 (fsp->access_mask & FILE_EXECUTE)))) {
3390                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3391                                 (int)SVAL(req->vwv+0, 0)));
3392                 reply_readbraw_error(xconn);
3393                 END_PROFILE(SMBreadbraw);
3394                 return;
3395         }
3396
3397         flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3398
3399         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3400         if(req->wct == 10) {
3401                 /*
3402                  * This is a large offset (64 bit) read.
3403                  */
3404
3405                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3406
3407                 if(startpos < 0) {
3408                         DEBUG(0,("reply_readbraw: negative 64 bit "
3409                                 "readraw offset (%.0f) !\n",
3410                                 (double)startpos ));
3411                         reply_readbraw_error(xconn);
3412                         END_PROFILE(SMBreadbraw);
3413                         return;
3414                 }
3415         }
3416
3417         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3418         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3419
3420         /* ensure we don't overrun the packet size */
3421         maxcount = MIN(65535,maxcount);
3422
3423         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3424             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3425             &lock);
3426
3427         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3428                 reply_readbraw_error(xconn);
3429                 END_PROFILE(SMBreadbraw);
3430                 return;
3431         }
3432
3433         if (fsp_stat(fsp) == 0) {
3434                 size = fsp->fsp_name->st.st_ex_size;
3435         }
3436
3437         if (startpos >= size) {
3438                 nread = 0;
3439         } else {
3440                 nread = MIN(maxcount,(size - startpos));
3441         }
3442
3443 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3444         if (nread < mincount)
3445                 nread = 0;
3446 #endif
3447
3448         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3449                 "min=%lu nread=%lu\n",
3450                 fsp_fnum_dbg(fsp), (double)startpos,
3451                 (unsigned long)maxcount,
3452                 (unsigned long)mincount,
3453                 (unsigned long)nread ) );
3454
3455         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3456
3457         DEBUG(5,("reply_readbraw finished\n"));
3458
3459         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3460
3461         END_PROFILE(SMBreadbraw);
3462         return;
3463 }
3464
3465 #undef DBGC_CLASS
3466 #define DBGC_CLASS DBGC_LOCKING
3467
3468 /****************************************************************************
3469  Reply to a lockread (core+ protocol).
3470 ****************************************************************************/
3471
3472 void reply_lockread(struct smb_request *req)
3473 {
3474         connection_struct *conn = req->conn;
3475         ssize_t nread = -1;
3476         char *data;
3477         off_t startpos;
3478         size_t numtoread;
3479         size_t maxtoread;
3480         NTSTATUS status;
3481         files_struct *fsp;
3482         struct byte_range_lock *br_lck = NULL;
3483         char *p = NULL;
3484         struct smbXsrv_connection *xconn = req->xconn;
3485
3486         START_PROFILE(SMBlockread);
3487
3488         if (req->wct < 5) {
3489                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3490                 END_PROFILE(SMBlockread);
3491                 return;
3492         }
3493
3494         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3495
3496         if (!check_fsp(conn, req, fsp)) {
3497                 END_PROFILE(SMBlockread);
3498                 return;
3499         }
3500
3501         if (!CHECK_READ(fsp,req)) {
3502                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3503                 END_PROFILE(SMBlockread);
3504                 return;
3505         }
3506
3507         numtoread = SVAL(req->vwv+1, 0);
3508         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3509
3510         /*
3511          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3512          * protocol request that predates the read/write lock concept. 
3513          * Thus instead of asking for a read lock here we need to ask
3514          * for a write lock. JRA.
3515          * Note that the requested lock size is unaffected by max_send.
3516          */
3517
3518         br_lck = do_lock(req->sconn->msg_ctx,
3519                         fsp,
3520                         (uint64_t)req->smbpid,
3521                         (uint64_t)numtoread,
3522                         (uint64_t)startpos,
3523                         WRITE_LOCK,
3524                         WINDOWS_LOCK,
3525                         False, /* Non-blocking lock. */
3526                         &status,
3527                         NULL);
3528         TALLOC_FREE(br_lck);
3529
3530         if (NT_STATUS_V(status)) {
3531                 reply_nterror(req, status);
3532                 END_PROFILE(SMBlockread);
3533                 return;
3534         }
3535
3536         /*
3537          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3538          */
3539         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3540
3541         if (numtoread > maxtoread) {
3542                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3543 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3544                         (unsigned int)numtoread, (unsigned int)maxtoread,
3545                         (unsigned int)xconn->smb1.sessions.max_send));
3546                 numtoread = maxtoread;
3547         }
3548
3549         reply_outbuf(req, 5, numtoread + 3);
3550
3551         data = smb_buf(req->outbuf) + 3;
3552
3553         nread = read_file(fsp,data,startpos,numtoread);
3554
3555         if (nread < 0) {
3556                 reply_nterror(req, map_nt_error_from_unix(errno));
3557                 END_PROFILE(SMBlockread);
3558                 return;
3559         }
3560
3561         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3562
3563         SSVAL(req->outbuf,smb_vwv0,nread);
3564         SSVAL(req->outbuf,smb_vwv5,nread+3);
3565         p = smb_buf(req->outbuf);
3566         SCVAL(p,0,0); /* pad byte. */
3567         SSVAL(p,1,nread);
3568
3569         DEBUG(3,("lockread %s num=%d nread=%d\n",
3570                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3571
3572         END_PROFILE(SMBlockread);
3573         return;
3574 }
3575
3576 #undef DBGC_CLASS
3577 #define DBGC_CLASS DBGC_ALL
3578
3579 /****************************************************************************
3580  Reply to a read.
3581 ****************************************************************************/
3582
3583 void reply_read(struct smb_request *req)
3584 {
3585         connection_struct *conn = req->conn;
3586         size_t numtoread;
3587         size_t maxtoread;
3588         ssize_t nread = 0;
3589         char *data;
3590         off_t startpos;
3591         files_struct *fsp;
3592         struct lock_struct lock;
3593         struct smbXsrv_connection *xconn = req->xconn;
3594
3595         START_PROFILE(SMBread);
3596
3597         if (req->wct < 3) {
3598                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3599                 END_PROFILE(SMBread);
3600                 return;
3601         }
3602
3603         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3604
3605         if (!check_fsp(conn, req, fsp)) {
3606                 END_PROFILE(SMBread);
3607                 return;
3608         }
3609
3610         if (!CHECK_READ(fsp,req)) {
3611                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3612                 END_PROFILE(SMBread);
3613                 return;
3614         }
3615
3616         numtoread = SVAL(req->vwv+1, 0);
3617         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3618
3619         /*
3620          * The requested read size cannot be greater than max_send. JRA.
3621          */
3622         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3623
3624         if (numtoread > maxtoread) {
3625                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3626 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3627                         (unsigned int)numtoread, (unsigned int)maxtoread,
3628                         (unsigned int)xconn->smb1.sessions.max_send));
3629                 numtoread = maxtoread;
3630         }
3631
3632         reply_outbuf(req, 5, numtoread+3);
3633
3634         data = smb_buf(req->outbuf) + 3;
3635
3636         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3637             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3638             &lock);
3639
3640         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3641                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3642                 END_PROFILE(SMBread);
3643                 return;
3644         }
3645
3646         if (numtoread > 0)
3647                 nread = read_file(fsp,data,startpos,numtoread);
3648
3649         if (nread < 0) {
3650                 reply_nterror(req, map_nt_error_from_unix(errno));
3651                 goto strict_unlock;
3652         }
3653
3654         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3655
3656         SSVAL(req->outbuf,smb_vwv0,nread);
3657         SSVAL(req->outbuf,smb_vwv5,nread+3);
3658         SCVAL(smb_buf(req->outbuf),0,1);
3659         SSVAL(smb_buf(req->outbuf),1,nread);
3660
3661         DEBUG(3, ("read %s num=%d nread=%d\n",
3662                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3663
3664 strict_unlock:
3665         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3666
3667         END_PROFILE(SMBread);
3668         return;
3669 }
3670
3671 /****************************************************************************
3672  Setup readX header.
3673 ****************************************************************************/
3674
3675 static int setup_readX_header(struct smb_request *req, char *outbuf,
3676                               size_t smb_maxcnt)
3677 {
3678         int outsize;
3679
3680         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3681
3682         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3683
3684         SCVAL(outbuf,smb_vwv0,0xFF);
3685         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3686         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3687         SSVAL(outbuf,smb_vwv6,
3688               (smb_wct - 4)     /* offset from smb header to wct */
3689               + 1               /* the wct field */
3690               + 12 * sizeof(uint16_t) /* vwv */
3691               + 2);             /* the buflen field */
3692         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3693         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3694         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3695         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3696         return outsize;
3697 }
3698
3699 /****************************************************************************
3700  Reply to a read and X - possibly using sendfile.
3701 ****************************************************************************/
3702
3703 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3704                             files_struct *fsp, off_t startpos,
3705                             size_t smb_maxcnt)
3706 {
3707         struct smbXsrv_connection *xconn = req->xconn;
3708         ssize_t nread = -1;
3709         struct lock_struct lock;
3710         int saved_errno = 0;
3711
3712         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3713             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3714             &lock);
3715
3716         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3717                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3718                 return;
3719         }
3720
3721         /*
3722          * We can only use sendfile on a non-chained packet
3723          * but we can use on a non-oplocked file. tridge proved this
3724          * on a train in Germany :-). JRA.
3725          */
3726
3727         if (!req_is_in_chain(req) &&
3728             !req->encrypted &&
3729             (fsp->base_fsp == NULL) &&
3730             (fsp->wcp == NULL) &&
3731             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3732                 uint8 headerbuf[smb_size + 12 * 2];
3733                 DATA_BLOB header;
3734
3735                 if(fsp_stat(fsp) == -1) {
3736                         reply_nterror(req, map_nt_error_from_unix(errno));
3737                         goto strict_unlock;
3738                 }
3739
3740                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3741                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3742                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3743                         /*
3744                          * We already know that we would do a short read, so don't
3745                          * try the sendfile() path.
3746                          */
3747                         goto nosendfile_read;
3748                 }
3749
3750                 /*
3751                  * Set up the packet header before send. We
3752                  * assume here the sendfile will work (get the
3753                  * correct amount of data).
3754                  */
3755
3756                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3757
3758                 construct_reply_common_req(req, (char *)headerbuf);
3759                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3760
3761                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3762                                          startpos, smb_maxcnt);
3763                 if (nread == -1) {
3764                         saved_errno = errno;
3765
3766                         /* Returning ENOSYS means no data at all was sent.
3767                            Do this as a normal read. */
3768                         if (errno == ENOSYS) {
3769                                 goto normal_read;
3770                         }
3771
3772                         /*
3773                          * Special hack for broken Linux with no working sendfile. If we
3774                          * return EINTR we sent the header but not the rest of the data.
3775                          * Fake this up by doing read/write calls.
3776                          */
3777
3778                         if (errno == EINTR) {
3779                                 /* Ensure we don't do this again. */
3780                                 set_use_sendfile(SNUM(conn), False);
3781                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3782                                 nread = fake_sendfile(xconn, fsp, startpos,
3783                                                       smb_maxcnt);
3784                                 if (nread == -1) {
3785                                         saved_errno = errno;
3786                                         DEBUG(0,("send_file_readX: "
3787                                                  "fake_sendfile failed for "
3788                                                  "file %s (%s) for client %s. "
3789                                                  "Terminating\n",
3790                                                  fsp_str_dbg(fsp),
3791                                                  smbXsrv_connection_dbg(xconn),
3792                                                  strerror(saved_errno)));
3793                                         errno = saved_errno;
3794                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3795                                 }
3796                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3797                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3798                                 /* No outbuf here means successful sendfile. */
3799                                 goto strict_unlock;
3800                         }
3801
3802                         DEBUG(0,("send_file_readX: sendfile failed for file "
3803                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3804                                  strerror(errno)));
3805                         exit_server_cleanly("send_file_readX sendfile failed");
3806                 } else if (nread == 0) {
3807                         /*
3808                          * Some sendfile implementations return 0 to indicate
3809                          * that there was a short read, but nothing was
3810                          * actually written to the socket.  In this case,
3811                          * fallback to the normal read path so the header gets
3812                          * the correct byte count.
3813                          */
3814                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3815                                   "falling back to the normal read: %s\n",
3816                                   fsp_str_dbg(fsp)));
3817                         goto normal_read;
3818                 }
3819
3820                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3821                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3822
3823                 /* Deal with possible short send. */
3824                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3825                         ssize_t ret;
3826
3827                         ret = sendfile_short_send(xconn, fsp, nread,
3828                                                   sizeof(headerbuf), smb_maxcnt);
3829                         if (ret == -1) {
3830                                 const char *r;
3831                                 r = "send_file_readX: sendfile_short_send failed";
3832                                 DEBUG(0,("%s for file %s (%s).\n",
3833                                          r, fsp_str_dbg(fsp), strerror(errno)));
3834                                 exit_server_cleanly(r);
3835                         }
3836                 }
3837                 /* No outbuf here means successful sendfile. */
3838                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3839                 SMB_PERFCOUNT_END(&req->pcd);
3840                 goto strict_unlock;
3841         }
3842
3843 normal_read:
3844
3845         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3846                 uint8 headerbuf[smb_size + 2*12];
3847                 ssize_t ret;
3848
3849                 construct_reply_common_req(req, (char *)headerbuf);
3850                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3851
3852                 /* Send out the header. */
3853                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3854                                  sizeof(headerbuf));
3855                 if (ret != sizeof(headerbuf)) {
3856                         saved_errno = errno;
3857                         /*
3858                          * Try and give an error message saying what
3859                          * client failed.
3860                          */
3861                         DEBUG(0,("send_file_readX: write_data failed for file "
3862                                  "%s (%s) for client %s. Terminating\n",
3863                                  fsp_str_dbg(fsp),
3864                                  smbXsrv_connection_dbg(xconn),
3865                                  strerror(saved_errno)));
3866                         errno = saved_errno;
3867                         exit_server_cleanly("send_file_readX sendfile failed");
3868                 }
3869                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3870                 if (nread == -1) {
3871                         saved_errno = errno;
3872                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3873                                  "%s (%s) for client %s. Terminating\n",
3874                                  fsp_str_dbg(fsp),
3875                                  smbXsrv_connection_dbg(xconn),
3876                                  strerror(saved_errno)));
3877                         errno = saved_errno;
3878                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3879                 }
3880                 goto strict_unlock;
3881         }
3882
3883 nosendfile_read:
3884
3885         reply_outbuf(req, 12, smb_maxcnt);
3886         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3887         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3888
3889         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3890         saved_errno = errno;
3891
3892         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3893
3894         if (nread < 0) {
3895                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3896                 return;
3897         }
3898
3899         setup_readX_header(req, (char *)req->outbuf, nread);
3900
3901         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3902                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3903         return;
3904
3905  strict_unlock:
3906         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3907         TALLOC_FREE(req->outbuf);
3908         return;
3909 }
3910
3911 /****************************************************************************
3912  Work out how much space we have for a read return.
3913 ****************************************************************************/
3914
3915 static size_t calc_max_read_pdu(const struct smb_request *req)
3916 {
3917         struct smbXsrv_connection *xconn = req->xconn;
3918
3919         if (xconn->protocol < PROTOCOL_NT1) {
3920                 return xconn->smb1.sessions.max_send;
3921         }
3922
3923         if (!lp_large_readwrite()) {
3924                 return xconn->smb1.sessions.max_send;
3925         }
3926
3927         if (req_is_in_chain(req)) {
3928                 return xconn->smb1.sessions.max_send;
3929         }
3930
3931         if (req->encrypted) {
3932                 /*
3933                  * Don't take encrypted traffic up to the
3934                  * limit. There are padding considerations
3935                  * that make that tricky.
3936                  */
3937                 return xconn->smb1.sessions.max_send;
3938         }
3939
3940         if (srv_is_signing_active(xconn)) {
3941                 return 0x1FFFF;
3942         }
3943
3944         if (!lp_unix_extensions()) {
3945                 return 0x1FFFF;
3946         }
3947
3948         /*
3949          * We can do ultra-large POSIX reads.
3950          */
3951         return 0xFFFFFF;
3952 }
3953
3954 /****************************************************************************
3955  Calculate how big a read can be. Copes with all clients. It's always
3956  safe to return a short read - Windows does this.
3957 ****************************************************************************/
3958
3959 static size_t calc_read_size(const struct smb_request *req,
3960                              size_t upper_size,
3961                              size_t lower_size)
3962 {
3963         struct smbXsrv_connection *xconn = req->xconn;
3964         size_t max_pdu = calc_max_read_pdu(req);
3965         size_t total_size = 0;
3966         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3967         size_t max_len = max_pdu - hdr_len;
3968
3969         /*
3970          * Windows explicitly ignores upper size of 0xFFFF.
3971          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3972          * We must do the same as these will never fit even in
3973          * an extended size NetBIOS packet.
3974          */
3975         if (upper_size == 0xFFFF) {
3976                 upper_size = 0;
3977         }
3978
3979         if (xconn->protocol < PROTOCOL_NT1) {
3980                 upper_size = 0;
3981         }
3982
3983         total_size = ((upper_size<<16) | lower_size);
3984
3985         /*
3986          * LARGE_READX test shows it's always safe to return
3987          * a short read. Windows does so.
3988          */
3989         return MIN(total_size, max_len);
3990 }
3991
3992 /****************************************************************************
3993  Reply to a read and X.
3994 ****************************************************************************/
3995
3996 void reply_read_and_X(struct smb_request *req)
3997 {
3998         connection_struct *conn = req->conn;
3999         files_struct *fsp;
4000         off_t startpos;
4001         size_t smb_maxcnt;
4002         size_t upper_size;
4003         bool big_readX = False;
4004 #if 0
4005         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4006 #endif
4007
4008         START_PROFILE(SMBreadX);
4009
4010         if ((req->wct != 10) && (req->wct != 12)) {
4011                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4012                 return;
4013         }
4014
4015         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4016         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4017         smb_maxcnt = SVAL(req->vwv+5, 0);
4018
4019         /* If it's an IPC, pass off the pipe handler. */
4020         if (IS_IPC(conn)) {
4021                 reply_pipe_read_and_X(req);
4022                 END_PROFILE(SMBreadX);
4023                 return;
4024         }
4025
4026         if (!check_fsp(conn, req, fsp)) {
4027                 END_PROFILE(SMBreadX);
4028                 return;
4029         }
4030
4031         if (!CHECK_READ(fsp,req)) {
4032                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4033                 END_PROFILE(SMBreadX);
4034                 return;
4035         }
4036
4037         upper_size = SVAL(req->vwv+7, 0);
4038         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4039         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4040                 /*
4041                  * This is a heuristic to avoid keeping large
4042                  * outgoing buffers around over long-lived aio
4043                  * requests.
4044                  */
4045                 big_readX = True;
4046         }
4047
4048         if (req->wct == 12) {
4049                 /*
4050                  * This is a large offset (64 bit) read.
4051                  */
4052                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4053
4054         }
4055
4056         if (!big_readX) {
4057                 NTSTATUS status = schedule_aio_read_and_X(conn,
4058                                         req,
4059                                         fsp,
4060                                         startpos,
4061                                         smb_maxcnt);
4062                 if (NT_STATUS_IS_OK(status)) {
4063                         /* Read scheduled - we're done. */
4064                         goto out;
4065                 }
4066                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4067                         /* Real error - report to client. */
4068                         END_PROFILE(SMBreadX);
4069                         reply_nterror(req, status);
4070                         return;
4071                 }
4072                 /* NT_STATUS_RETRY - fall back to sync read. */
4073         }
4074
4075         smbd_lock_socket(req->xconn);
4076         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4077         smbd_unlock_socket(req->xconn);
4078
4079  out:
4080         END_PROFILE(SMBreadX);
4081         return;
4082 }
4083
4084 /****************************************************************************
4085  Error replies to writebraw must have smb_wct == 1. Fix this up.
4086 ****************************************************************************/
4087
4088 void error_to_writebrawerr(struct smb_request *req)
4089 {
4090         uint8 *old_outbuf = req->outbuf;
4091
4092         reply_outbuf(req, 1, 0);
4093
4094         memcpy(req->outbuf, old_outbuf, smb_size);
4095         TALLOC_FREE(old_outbuf);
4096 }
4097
4098 /****************************************************************************
4099  Read 4 bytes of a smb packet and return the smb length of the packet.
4100  Store the result in the buffer. This version of the function will
4101  never return a session keepalive (length of zero).
4102  Timeout is in milliseconds.
4103 ****************************************************************************/
4104
4105 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4106                                 size_t *len)
4107 {
4108         uint8_t msgtype = NBSSkeepalive;
4109
4110         while (msgtype == NBSSkeepalive) {
4111                 NTSTATUS status;
4112
4113                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4114                                                           len);
4115                 if (!NT_STATUS_IS_OK(status)) {
4116                         char addr[INET6_ADDRSTRLEN];
4117                         /* Try and give an error message
4118                          * saying what client failed. */
4119                         DEBUG(0, ("read_fd_with_timeout failed for "
4120                                   "client %s read error = %s.\n",
4121                                   get_peer_addr(fd,addr,sizeof(addr)),
4122                                   nt_errstr(status)));
4123                         return status;
4124                 }
4125
4126                 msgtype = CVAL(inbuf, 0);
4127         }
4128
4129         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4130                   (unsigned long)len));
4131
4132         return NT_STATUS_OK;
4133 }
4134
4135 /****************************************************************************
4136  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4137 ****************************************************************************/
4138
4139 void reply_writebraw(struct smb_request *req)
4140 {
4141         connection_struct *conn = req->conn;
4142         struct smbXsrv_connection *xconn = req->xconn;
4143         char *buf = NULL;
4144         ssize_t nwritten=0;
4145         ssize_t total_written=0;
4146         size_t numtowrite=0;
4147         size_t tcount;
4148         off_t startpos;
4149         const char *data=NULL;
4150         bool write_through;
4151         files_struct *fsp;
4152         struct lock_struct lock;
4153         NTSTATUS status;
4154
4155         START_PROFILE(SMBwritebraw);
4156
4157         /*
4158          * If we ever reply with an error, it must have the SMB command
4159          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4160          * we're finished.
4161          */
4162         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4163
4164         if (srv_is_signing_active(xconn)) {
4165                 END_PROFILE(SMBwritebraw);
4166                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4167                                 "raw reads/writes are disallowed.");
4168         }
4169
4170         if (req->wct < 12) {
4171                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4172                 error_to_writebrawerr(req);
4173                 END_PROFILE(SMBwritebraw);
4174                 return;
4175         }
4176
4177         if (xconn->smb1.echo_handler.trusted_fde) {
4178                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4179                          "'async smb echo handler = yes'\n"));
4180                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4181                 error_to_writebrawerr(req);
4182                 END_PROFILE(SMBwritebraw);
4183                 return;
4184         }
4185
4186         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4187         if (!check_fsp(conn, req, fsp)) {
4188                 error_to_writebrawerr(req);
4189                 END_PROFILE(SMBwritebraw);
4190                 return;
4191         }
4192
4193         if (!CHECK_WRITE(fsp)) {
4194                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4195                 error_to_writebrawerr(req);
4196                 END_PROFILE(SMBwritebraw);
4197                 return;
4198         }
4199
4200         tcount = IVAL(req->vwv+1, 0);
4201         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4202         write_through = BITSETW(req->vwv+7,0);
4203
4204         /* We have to deal with slightly different formats depending
4205                 on whether we are using the core+ or lanman1.0 protocol */
4206
4207         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4208                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4209                 data = smb_buf_const(req->inbuf);
4210         } else {
4211                 numtowrite = SVAL(req->vwv+10, 0);
4212                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4213         }
4214
4215         /* Ensure we don't write bytes past the end of this packet. */
4216         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4217                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4218                 error_to_writebrawerr(req);
4219                 END_PROFILE(SMBwritebraw);
4220                 return;
4221         }
4222
4223         if (!fsp->print_file) {
4224                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4225                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4226                     &lock);
4227
4228                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4229                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4230                         error_to_writebrawerr(req);
4231                         END_PROFILE(SMBwritebraw);
4232                         return;
4233                 }
4234         }
4235
4236         if (numtowrite>0) {
4237                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4238         }
4239
4240         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4241                         "wrote=%d sync=%d\n",
4242                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4243                 (int)nwritten, (int)write_through));
4244
4245         if (nwritten < (ssize_t)numtowrite)  {
4246                 reply_nterror(req, NT_STATUS_DISK_FULL);
4247                 error_to_writebrawerr(req);
4248                 goto strict_unlock;
4249         }
4250
4251         total_written = nwritten;
4252
4253         /* Allocate a buffer of 64k + length. */
4254         buf = talloc_array(NULL, char, 65540);
4255         if (!buf) {
4256                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4257                 error_to_writebrawerr(req);
4258                 goto strict_unlock;
4259         }
4260
4261         /* Return a SMBwritebraw message to the redirector to tell
4262          * it to send more bytes */
4263
4264         memcpy(buf, req->inbuf, smb_size);
4265         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4266         SCVAL(buf,smb_com,SMBwritebraw);
4267         SSVALS(buf,smb_vwv0,0xFFFF);
4268         show_msg(buf);
4269         if (!srv_send_smb(req->sconn,
4270                           buf,
4271                           false, 0, /* no signing */
4272                           IS_CONN_ENCRYPTED(conn),
4273                           &req->pcd)) {
4274                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4275                         "failed.");
4276         }
4277
4278         /* Now read the raw data into the buffer and write it */
4279         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4280                                  &numtowrite);
4281         if (!NT_STATUS_IS_OK(status)) {
4282                 exit_server_cleanly("secondary writebraw failed");
4283         }
4284
4285         /* Set up outbuf to return the correct size */
4286         reply_outbuf(req, 1, 0);
4287
4288         if (numtowrite != 0) {
4289
4290                 if (numtowrite > 0xFFFF) {
4291                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4292                                 "raw requested (%u). Terminating\n",
4293                                 (unsigned int)numtowrite ));
4294                         exit_server_cleanly("secondary writebraw failed");
4295                 }
4296
4297                 if (tcount > nwritten+numtowrite) {
4298                         DEBUG(3,("reply_writebraw: Client overestimated the "
4299                                 "write %d %d %d\n",
4300                                 (int)tcount,(int)nwritten,(int)numtowrite));
4301                 }
4302
4303                 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4304
4305                 if (!NT_STATUS_IS_OK(status)) {
4306                         /* Try and give an error message
4307                          * saying what client failed. */
4308                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4309                                   "raw read failed (%s) for client %s. "
4310                                   "Terminating\n", nt_errstr(status),
4311                                   smbXsrv_connection_dbg(xconn)));
4312                         exit_server_cleanly("secondary writebraw failed");
4313                 }
4314
4315                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4316                 if (nwritten == -1) {
4317                         TALLOC_FREE(buf);
4318                         reply_nterror(req, map_nt_error_from_unix(errno));
4319                         error_to_writebrawerr(req);
4320                         goto strict_unlock;
4321                 }
4322
4323                 if (nwritten < (ssize_t)numtowrite) {
4324                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4325                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4326                 }
4327
4328                 if (nwritten > 0) {
4329                         total_written += nwritten;
4330                 }
4331         }
4332
4333         TALLOC_FREE(buf);
4334         SSVAL(req->outbuf,smb_vwv0,total_written);
4335
4336         status = sync_file(conn, fsp, write_through);
4337         if (!NT_STATUS_IS_OK(status)) {
4338                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4339                          fsp_str_dbg(fsp), nt_errstr(status)));
4340                 reply_nterror(req, status);
4341                 error_to_writebrawerr(req);
4342                 goto strict_unlock;
4343         }
4344
4345         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4346                 "wrote=%d\n",
4347                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4348                 (int)total_written));
4349
4350         if (!fsp->print_file) {
4351                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4352         }
4353
4354         /* We won't return a status if write through is not selected - this
4355          * follows what WfWg does */
4356         END_PROFILE(SMBwritebraw);
4357
4358         if (!write_through && total_written==tcount) {
4359
4360 #if RABBIT_PELLET_FIX
4361                 /*
4362                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4363                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4364                  * JRA.
4365                  */
4366                 if (!send_keepalive(xconn->transport.sock)) {
4367                         exit_server_cleanly("reply_writebraw: send of "
4368                                 "keepalive failed");
4369                 }
4370 #endif
4371                 TALLOC_FREE(req->outbuf);
4372         }
4373         return;
4374
4375 strict_unlock:
4376         if (!fsp->print_file) {
4377                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4378         }
4379
4380         END_PROFILE(SMBwritebraw);
4381         return;
4382 }
4383
4384 #undef DBGC_CLASS
4385 #define DBGC_CLASS DBGC_LOCKING
4386
4387 /****************************************************************************
4388  Reply to a writeunlock (core+).
4389 ****************************************************************************/
4390
4391 void reply_writeunlock(struct smb_request *req)
4392 {
4393         connection_struct *conn = req->conn;
4394         ssize_t nwritten = -1;
4395         size_t numtowrite;
4396         off_t startpos;
4397         const char *data;
4398         NTSTATUS status = NT_STATUS_OK;
4399         files_struct *fsp;
4400         struct lock_struct lock;
4401         int saved_errno = 0;
4402
4403         START_PROFILE(SMBwriteunlock);
4404
4405         if (req->wct < 5) {
4406                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4407                 END_PROFILE(SMBwriteunlock);
4408                 return;
4409         }
4410
4411         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4412
4413         if (!check_fsp(conn, req, fsp)) {
4414                 END_PROFILE(SMBwriteunlock);
4415                 return;
4416         }
4417
4418         if (!CHECK_WRITE(fsp)) {
4419                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4420                 END_PROFILE(SMBwriteunlock);
4421                 return;
4422         }
4423
4424         numtowrite = SVAL(req->vwv+1, 0);
4425         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4426         data = (const char *)req->buf + 3;
4427
4428         if (!fsp->print_file && numtowrite > 0) {
4429                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4430                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4431                     &lock);
4432
4433                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4434                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4435                         END_PROFILE(SMBwriteunlock);
4436                         return;
4437                 }
4438         }
4439
4440         /* The special X/Open SMB protocol handling of
4441            zero length writes is *NOT* done for
4442            this call */
4443         if(numtowrite == 0) {
4444                 nwritten = 0;
4445         } else {
4446                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4447                 saved_errno = errno;
4448         }
4449
4450         status = sync_file(conn, fsp, False /* write through */);
4451         if (!NT_STATUS_IS_OK(status)) {
4452                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4453                          fsp_str_dbg(fsp), nt_errstr(status)));
4454                 reply_nterror(req, status);
4455                 goto strict_unlock;
4456         }
4457
4458         if(nwritten < 0) {
4459                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4460                 goto strict_unlock;
4461         }
4462
4463         if((nwritten < numtowrite) && (numtowrite != 0)) {
4464                 reply_nterror(req, NT_STATUS_DISK_FULL);
4465                 goto strict_unlock;
4466         }
4467
4468         if (numtowrite && !fsp->print_file) {
4469                 status = do_unlock(req->sconn->msg_ctx,
4470                                 fsp,
4471                                 (uint64_t)req->smbpid,
4472                                 (uint64_t)numtowrite, 
4473                                 (uint64_t)startpos,
4474                                 WINDOWS_LOCK);
4475
4476                 if (NT_STATUS_V(status)) {
4477                         reply_nterror(req, status);
4478                         goto strict_unlock;
4479                 }
4480         }
4481
4482         reply_outbuf(req, 1, 0);
4483
4484         SSVAL(req->outbuf,smb_vwv0,nwritten);
4485
4486         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4487                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4488
4489 strict_unlock:
4490         if (numtowrite && !fsp->print_file) {
4491                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4492         }
4493
4494         END_PROFILE(SMBwriteunlock);
4495         return;
4496 }
4497
4498 #undef DBGC_CLASS
4499 #define DBGC_CLASS DBGC_ALL
4500
4501 /****************************************************************************
4502  Reply to a write.
4503 ****************************************************************************/
4504
4505 void reply_write(struct smb_request *req)
4506 {
4507         connection_struct *conn = req->conn;
4508         size_t numtowrite;
4509         ssize_t nwritten = -1;
4510         off_t startpos;
4511         const char *data;
4512         files_struct *fsp;
4513         struct lock_struct lock;
4514         NTSTATUS status;
4515         int saved_errno = 0;
4516
4517         START_PROFILE(SMBwrite);
4518
4519         if (req->wct < 5) {
4520                 END_PROFILE(SMBwrite);
4521                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4522                 return;
4523         }
4524
4525         /* If it's an IPC, pass off the pipe handler. */
4526         if (IS_IPC(conn)) {
4527                 reply_pipe_write(req);
4528                 END_PROFILE(SMBwrite);
4529                 return;
4530         }
4531
4532         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4533
4534         if (!check_fsp(conn, req, fsp)) {
4535                 END_PROFILE(SMBwrite);
4536                 return;
4537         }
4538
4539         if (!CHECK_WRITE(fsp)) {
4540                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4541                 END_PROFILE(SMBwrite);
4542                 return;
4543         }
4544
4545         numtowrite = SVAL(req->vwv+1, 0);
4546         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4547         data = (const char *)req->buf + 3;
4548
4549         if (!fsp->print_file) {
4550                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4551                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4552                         &lock);
4553
4554                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4555                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4556                         END_PROFILE(SMBwrite);
4557                         return;
4558                 }
4559         }
4560
4561         /*
4562          * X/Open SMB protocol says that if smb_vwv1 is
4563          * zero then the file size should be extended or
4564          * truncated to the size given in smb_vwv[2-3].
4565          */
4566
4567         if(numtowrite == 0) {
4568                 /*
4569                  * This is actually an allocate call, and set EOF. JRA.
4570                  */
4571                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4572                 if (nwritten < 0) {
4573                         reply_nterror(req, NT_STATUS_DISK_FULL);
4574                         goto strict_unlock;
4575                 }
4576                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4577                 if (nwritten < 0) {
4578                         reply_nterror(req, NT_STATUS_DISK_FULL);
4579                         goto strict_unlock;
4580                 }
4581                 trigger_write_time_update_immediate(fsp);
4582         } else {
4583                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4584         }
4585
4586         status = sync_file(conn, fsp, False);
4587         if (!NT_STATUS_IS_OK(status)) {
4588                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4589                          fsp_str_dbg(fsp), nt_errstr(status)));
4590                 reply_nterror(req, status);
4591                 goto strict_unlock;
4592         }
4593
4594         if(nwritten < 0) {
4595                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4596                 goto strict_unlock;
4597         }
4598
4599         if((nwritten == 0) && (numtowrite != 0)) {
4600                 reply_nterror(req, NT_STATUS_DISK_FULL);
4601                 goto strict_unlock;
4602         }
4603
4604         reply_outbuf(req, 1, 0);
4605
4606         SSVAL(req->outbuf,smb_vwv0,nwritten);
4607
4608         if (nwritten < (ssize_t)numtowrite) {
4609                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4610                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4611         }
4612
4613         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4614
4615 strict_unlock:
4616         if (!fsp->print_file) {
4617                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4618         }
4619
4620         END_PROFILE(SMBwrite);
4621         return;
4622 }
4623
4624 /****************************************************************************
4625  Ensure a buffer is a valid writeX for recvfile purposes.
4626 ****************************************************************************/
4627
4628 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4629                                                 (2*14) + /* word count (including bcc) */ \
4630                                                 1 /* pad byte */)
4631
4632 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4633                             const uint8_t *inbuf)
4634 {
4635         size_t numtowrite;
4636         unsigned int doff = 0;
4637         size_t len = smb_len_large(inbuf);
4638         uint16_t fnum;
4639         struct smbXsrv_open *op = NULL;
4640         struct files_struct *fsp = NULL;
4641         NTSTATUS status;
4642
4643         if (is_encrypted_packet(inbuf)) {
4644                 /* Can't do this on encrypted
4645                  * connections. */
4646                 return false;
4647         }
4648
4649         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4650                 return false;
4651         }
4652
4653         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4654                         CVAL(inbuf,smb_wct) != 14) {
4655                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4656                         "invalid word length.\n"));
4657                 return false;
4658         }
4659
4660         fnum = SVAL(inbuf, smb_vwv2);
4661         status = smb1srv_open_lookup(xconn,
4662                                      fnum,
4663                                      0, /* now */
4664                                      &op);
4665         if (!NT_STATUS_IS_OK(status)) {
4666                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4667                 return false;
4668         }
4669         fsp = op->compat;
4670         if (fsp == NULL) {
4671                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4672                 return false;
4673         }
4674         if (fsp->conn == NULL) {
4675                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4676                 return false;
4677         }
4678
4679         if (IS_IPC(fsp->conn)) {
4680                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4681                 return false;
4682         }
4683         if (IS_PRINT(fsp->conn)) {
4684                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4685                 return false;
4686         }
4687         doff = SVAL(inbuf,smb_vwv11);
4688
4689         numtowrite = SVAL(inbuf,smb_vwv10);
4690
4691         if (len > doff && len - doff > 0xFFFF) {
4692                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4693         }
4694
4695         if (numtowrite == 0) {
4696                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4697                 return false;
4698         }
4699
4700         /* Ensure the sizes match up. */
4701         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4702                 /* no pad byte...old smbclient :-( */
4703                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4704                         (unsigned int)doff,
4705                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4706                 return false;
4707         }
4708
4709         if (len - doff != numtowrite) {
4710                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4711                         "len = %u, doff = %u, numtowrite = %u\n",
4712                         (unsigned int)len,
4713                         (unsigned int)doff,
4714                         (unsigned int)numtowrite ));
4715                 return false;
4716         }
4717
4718         DEBUG(10,("is_valid_writeX_buffer: true "
4719                 "len = %u, doff = %u, numtowrite = %u\n",
4720                 (unsigned int)len,
4721                 (unsigned int)doff,
4722                 (unsigned int)numtowrite ));
4723
4724         return true;
4725 }
4726
4727 /****************************************************************************
4728  Reply to a write and X.
4729 ****************************************************************************/
4730
4731 void reply_write_and_X(struct smb_request *req)
4732 {
4733         connection_struct *conn = req->conn;
4734         struct smbXsrv_connection *xconn = req->xconn;
4735         files_struct *fsp;
4736         struct lock_struct lock;
4737         off_t startpos;
4738         size_t numtowrite;
4739         bool write_through;
4740         ssize_t nwritten;
4741         unsigned int smb_doff;
4742         unsigned int smblen;
4743         const char *data;
4744         NTSTATUS status;
4745         int saved_errno = 0;
4746
4747         START_PROFILE(SMBwriteX);
4748
4749         if ((req->wct != 12) && (req->wct != 14)) {
4750                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4751                 goto out;
4752         }
4753
4754         numtowrite = SVAL(req->vwv+10, 0);
4755         smb_doff = SVAL(req->vwv+11, 0);
4756         smblen = smb_len(req->inbuf);
4757
4758         if (req->unread_bytes > 0xFFFF ||
4759                         (smblen > smb_doff &&
4760                                 smblen - smb_doff > 0xFFFF)) {
4761                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4762         }
4763
4764         if (req->unread_bytes) {
4765                 /* Can't do a recvfile write on IPC$ */
4766                 if (IS_IPC(conn)) {
4767                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768                         goto out;
4769                 }
4770                 if (numtowrite != req->unread_bytes) {
4771                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4772                         goto out;
4773                 }
4774         } else {
4775                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4776                                 smb_doff + numtowrite > smblen) {
4777                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778                         goto out;
4779                 }
4780         }
4781
4782         /* If it's an IPC, pass off the pipe handler. */
4783         if (IS_IPC(conn)) {
4784                 if (req->unread_bytes) {
4785                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4786                         goto out;
4787                 }
4788                 reply_pipe_write_and_X(req);
4789                 goto out;
4790         }
4791
4792         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4793         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4794         write_through = BITSETW(req->vwv+7,0);
4795
4796         if (!check_fsp(conn, req, fsp)) {
4797                 goto out;
4798         }
4799
4800         if (!CHECK_WRITE(fsp)) {
4801                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4802                 goto out;
4803         }
4804
4805         data = smb_base(req->inbuf) + smb_doff;
4806
4807         if(req->wct == 14) {
4808                 /*
4809                  * This is a large offset (64 bit) write.
4810                  */
4811                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4812
4813         }
4814
4815         /* X/Open SMB protocol says that, unlike SMBwrite
4816         if the length is zero then NO truncation is
4817         done, just a write of zero. To truncate a file,
4818         use SMBwrite. */
4819
4820         if(numtowrite == 0) {
4821                 nwritten = 0;
4822         } else {
4823                 if (req->unread_bytes == 0) {
4824                         status = schedule_aio_write_and_X(conn,
4825                                                 req,
4826                                                 fsp,
4827                                                 data,
4828                                                 startpos,
4829                                                 numtowrite);
4830
4831                         if (NT_STATUS_IS_OK(status)) {
4832                                 /* write scheduled - we're done. */
4833                                 goto out;
4834                         }
4835                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4836                                 /* Real error - report to client. */
4837                                 reply_nterror(req, status);
4838                                 goto out;
4839                         }
4840                         /* NT_STATUS_RETRY - fall through to sync write. */
4841                 }
4842
4843                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4844                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4845                     &lock);
4846
4847                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4848                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4849                         goto out;
4850                 }
4851
4852                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4853                 saved_errno = errno;
4854
4855                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4856         }
4857
4858         if(nwritten < 0) {
4859                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4860                 goto out;
4861         }
4862
4863         if((nwritten == 0) && (numtowrite != 0)) {
4864                 reply_nterror(req, NT_STATUS_DISK_FULL);
4865                 goto out;
4866         }
4867
4868         reply_outbuf(req, 6, 0);
4869         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4870         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4871         SSVAL(req->outbuf,smb_vwv2,nwritten);
4872         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4873
4874         DEBUG(3,("writeX %s num=%d wrote=%d\n",
4875                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4876
4877         status = sync_file(conn, fsp, write_through);
4878         if (!NT_STATUS_IS_OK(status)) {
4879                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4880                          fsp_str_dbg(fsp), nt_errstr(status)));
4881                 reply_nterror(req, status);
4882                 goto out;
4883         }
4884
4885         END_PROFILE(SMBwriteX);
4886         return;
4887
4888 out:
4889         if (req->unread_bytes) {
4890                 /* writeX failed. drain socket. */
4891                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4892                                 req->unread_bytes) {
4893                         smb_panic("failed to drain pending bytes");
4894                 }
4895                 req->unread_bytes = 0;
4896         }
4897
4898         END_PROFILE(SMBwriteX);
4899         return;
4900 }
4901
4902 /****************************************************************************
4903  Reply to a lseek.
4904 ****************************************************************************/
4905
4906 void reply_lseek(struct smb_request *req)
4907 {
4908         connection_struct *conn = req->conn;
4909         off_t startpos;
4910         off_t res= -1;
4911         int mode,umode;
4912         files_struct *fsp;
4913
4914         START_PROFILE(SMBlseek);
4915
4916         if (req->wct < 4) {
4917                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4918                 END_PROFILE(SMBlseek);
4919                 return;
4920         }
4921
4922         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4923
4924         if (!check_fsp(conn, req, fsp)) {
4925                 return;
4926         }
4927
4928         flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4929
4930         mode = SVAL(req->vwv+1, 0) & 3;
4931         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4932         startpos = (off_t)IVALS(req->vwv+2, 0);
4933
4934         switch (mode) {
4935                 case 0:
4936                         umode = SEEK_SET;
4937                         res = startpos;
4938                         break;
4939                 case 1:
4940                         umode = SEEK_CUR;
4941                         res = fsp->fh->pos + startpos;
4942                         break;
4943                 case 2:
4944                         umode = SEEK_END;
4945                         break;
4946                 default:
4947                         umode = SEEK_SET;
4948                         res = startpos;
4949                         break;
4950         }
4951
4952         if (umode == SEEK_END) {
4953                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4954                         if(errno == EINVAL) {
4955                                 off_t current_pos = startpos;
4956
4957                                 if(fsp_stat(fsp) == -1) {
4958                                         reply_nterror(req,
4959                                                 map_nt_error_from_unix(errno));
4960                                         END_PROFILE(SMBlseek);
4961                                         return;
4962                                 }
4963
4964                                 current_pos += fsp->fsp_name->st.st_ex_size;
4965                                 if(current_pos < 0)
4966                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4967                         }
4968                 }
4969
4970                 if(res == -1) {
4971                         reply_nterror(req, map_nt_error_from_unix(errno));
4972                         END_PROFILE(SMBlseek);
4973                         return;
4974                 }
4975         }
4976
4977         fsp->fh->pos = res;
4978
4979         reply_outbuf(req, 2, 0);
4980         SIVAL(req->outbuf,smb_vwv0,res);
4981
4982         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4983                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4984
4985         END_PROFILE(SMBlseek);
4986         return;
4987 }
4988
4989 /****************************************************************************
4990  Reply to a flush.
4991 ****************************************************************************/
4992
4993 void reply_flush(struct smb_request *req)
4994 {
4995         connection_struct *conn = req->conn;
4996         uint16 fnum;
4997         files_struct *fsp;
4998
4999         START_PROFILE(SMBflush);
5000
5001         if (req->wct < 1) {
5002                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5003                 return;
5004         }
5005
5006         fnum = SVAL(req->vwv+0, 0);
5007         fsp = file_fsp(req, fnum);
5008
5009         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5010                 return;
5011         }
5012
5013         if (!fsp) {
5014                 file_sync_all(conn);
5015         } else {
5016                 NTSTATUS status = sync_file(conn, fsp, True);
5017                 if (!NT_STATUS_IS_OK(status)) {
5018                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5019                                 fsp_str_dbg(fsp), nt_errstr(status)));
5020                         reply_nterror(req, status);
5021                         END_PROFILE(SMBflush);
5022                         return;
5023                 }
5024         }
5025
5026         reply_outbuf(req, 0, 0);
5027
5028         DEBUG(3,("flush\n"));
5029         END_PROFILE(SMBflush);
5030         return;
5031 }
5032
5033 /****************************************************************************
5034  Reply to a exit.
5035  conn POINTER CAN BE NULL HERE !
5036 ****************************************************************************/
5037
5038 void reply_exit(struct smb_request *req)
5039 {
5040         START_PROFILE(SMBexit);
5041
5042         file_close_pid(req->sconn, req->smbpid, req->vuid);
5043
5044         reply_outbuf(req, 0, 0);
5045
5046         DEBUG(3,("exit\n"));
5047
5048         END_PROFILE(SMBexit);
5049         return;
5050 }
5051
5052 struct reply_close_state {
5053         files_struct *fsp;
5054         struct smb_request *smbreq;
5055 };
5056
5057 static void do_smb1_close(struct tevent_req *req);
5058
5059 void reply_close(struct smb_request *req)
5060 {
5061         connection_struct *conn = req->conn;
5062         NTSTATUS status = NT_STATUS_OK;
5063         files_struct *fsp = NULL;
5064         START_PROFILE(SMBclose);
5065
5066         if (req->wct < 3) {
5067                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5068                 END_PROFILE(SMBclose);
5069                 return;
5070         }
5071
5072         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5073
5074         /*
5075          * We can only use check_fsp if we know it's not a directory.
5076          */
5077
5078         if (!check_fsp_open(conn, req, fsp)) {
5079                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5080                 END_PROFILE(SMBclose);
5081                 return;
5082         }
5083
5084         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5085                   fsp->is_directory ? "directory" : "file",
5086                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5087                   conn->num_files_open));
5088
5089         if (!fsp->is_directory) {
5090                 time_t t;
5091
5092                 /*
5093                  * Take care of any time sent in the close.
5094                  */
5095
5096                 t = srv_make_unix_date3(req->vwv+1);
5097                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5098         }
5099
5100         if (fsp->num_aio_requests != 0) {
5101
5102                 struct reply_close_state *state;
5103
5104                 DEBUG(10, ("closing with aio %u requests pending\n",
5105                            fsp->num_aio_requests));
5106
5107                 /*
5108                  * We depend on the aio_extra destructor to take care of this
5109                  * close request once fsp->num_aio_request drops to 0.
5110                  */
5111
5112                 fsp->deferred_close = tevent_wait_send(
5113                         fsp, fsp->conn->sconn->ev_ctx);
5114                 if (fsp->deferred_close == NULL) {
5115                         status = NT_STATUS_NO_MEMORY;
5116                         goto done;
5117                 }
5118
5119                 state = talloc(fsp, struct reply_close_state);
5120                 if (state == NULL) {
5121                         TALLOC_FREE(fsp->deferred_close);
5122                         status = NT_STATUS_NO_MEMORY;
5123                         goto done;
5124                 }
5125                 state->fsp = fsp;
5126                 state->smbreq = talloc_move(fsp, &req);
5127                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5128                                         state);
5129                 END_PROFILE(SMBclose);
5130                 return;
5131         }
5132
5133         /*
5134          * close_file() returns the unix errno if an error was detected on
5135          * close - normally this is due to a disk full error. If not then it
5136          * was probably an I/O error.
5137          */
5138
5139         status = close_file(req, fsp, NORMAL_CLOSE);
5140 done:
5141         if (!NT_STATUS_IS_OK(status)) {
5142                 reply_nterror(req, status);
5143                 END_PROFILE(SMBclose);
5144                 return;
5145         }
5146
5147         reply_outbuf(req, 0, 0);
5148         END_PROFILE(SMBclose);
5149         return;
5150 }
5151
5152 static void do_smb1_close(struct tevent_req *req)
5153 {
5154         struct reply_close_state *state = tevent_req_callback_data(
5155                 req, struct reply_close_state);
5156         struct smb_request *smbreq;
5157         NTSTATUS status;
5158         int ret;
5159
5160         ret = tevent_wait_recv(req);
5161         TALLOC_FREE(req);
5162         if (ret != 0) {
5163                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5164                            strerror(ret)));
5165                 /*
5166                  * Continue anyway, this should never happen
5167                  */
5168         }
5169
5170         /*
5171          * fsp->smb2_close_request right now is a talloc grandchild of
5172          * fsp. When we close_file(fsp), it would go with it. No chance to
5173          * reply...
5174          */
5175         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5176
5177         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5178         if (NT_STATUS_IS_OK(status)) {
5179                 reply_outbuf(smbreq, 0, 0);
5180         } else {
5181                 reply_nterror(smbreq, status);
5182         }
5183         if (!srv_send_smb(smbreq->sconn,
5184                         (char *)smbreq->outbuf,
5185                         true,
5186                         smbreq->seqnum+1,
5187                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5188                         NULL)) {
5189                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5190                                     "failed.");
5191         }
5192         TALLOC_FREE(smbreq);
5193 }
5194
5195 /****************************************************************************
5196  Reply to a writeclose (Core+ protocol).
5197 ****************************************************************************/
5198
5199 void reply_writeclose(struct smb_request *req)
5200 {
5201         connection_struct *conn = req->conn;
5202         size_t numtowrite;
5203         ssize_t nwritten = -1;
5204         NTSTATUS close_status = NT_STATUS_OK;
5205         off_t startpos;
5206         const char *data;
5207         struct timespec mtime;
5208         files_struct *fsp;
5209         struct lock_struct lock;
5210
5211         START_PROFILE(SMBwriteclose);
5212
5213         if (req->wct < 6) {
5214                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5215                 END_PROFILE(SMBwriteclose);
5216                 return;
5217         }
5218
5219         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5220
5221         if (!check_fsp(conn, req, fsp)) {
5222                 END_PROFILE(SMBwriteclose);
5223                 return;
5224         }
5225         if (!CHECK_WRITE(fsp)) {
5226                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5227                 END_PROFILE(SMBwriteclose);
5228                 return;
5229         }
5230
5231         numtowrite = SVAL(req->vwv+1, 0);
5232         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5233         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5234         data = (const char *)req->buf + 1;
5235
5236         if (fsp->print_file == NULL) {
5237                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5238                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5239                     &lock);
5240
5241                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5242                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5243                         END_PROFILE(SMBwriteclose);
5244                         return;
5245                 }
5246         }
5247
5248         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5249
5250         if (fsp->print_file == NULL) {
5251                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5252         }
5253
5254         set_close_write_time(fsp, mtime);
5255
5256         /*
5257          * More insanity. W2K only closes the file if writelen > 0.
5258          * JRA.
5259          */
5260
5261         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5262                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5263                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5264
5265         if (numtowrite) {
5266                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5267                          "file %s\n", fsp_str_dbg(fsp)));
5268                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5269                 fsp = NULL;
5270         }
5271
5272         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5273                 reply_nterror(req, NT_STATUS_DISK_FULL);
5274                 goto out;
5275         }
5276
5277         if(!NT_STATUS_IS_OK(close_status)) {
5278                 reply_nterror(req, close_status);
5279                 goto out;
5280         }
5281
5282         reply_outbuf(req, 1, 0);
5283
5284         SSVAL(req->outbuf,smb_vwv0,nwritten);
5285
5286 out:
5287
5288         END_PROFILE(SMBwriteclose);
5289         return;
5290 }
5291
5292 #undef DBGC_CLASS
5293 #define DBGC_CLASS DBGC_LOCKING
5294
5295 /****************************************************************************
5296  Reply to a lock.
5297 ****************************************************************************/
5298
5299 void reply_lock(struct smb_request *req)
5300 {
5301         connection_struct *conn = req->conn;
5302         uint64_t count,offset;
5303         NTSTATUS status;
5304         files_struct *fsp;
5305         struct byte_range_lock *br_lck = NULL;
5306
5307         START_PROFILE(SMBlock);
5308
5309         if (req->wct < 5) {
5310                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5311                 END_PROFILE(SMBlock);
5312                 return;
5313         }
5314
5315         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5316
5317         if (!check_fsp(conn, req, fsp)) {
5318                 END_PROFILE(SMBlock);
5319                 return;
5320         }
5321
5322         count = (uint64_t)IVAL(req->vwv+1, 0);
5323         offset = (uint64_t)IVAL(req->vwv+3, 0);
5324
5325         DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5326                  fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5327
5328         br_lck = do_lock(req->sconn->msg_ctx,
5329                         fsp,
5330                         (uint64_t)req->smbpid,
5331                         count,
5332                         offset,
5333                         WRITE_LOCK,
5334                         WINDOWS_LOCK,
5335                         False, /* Non-blocking lock. */
5336                         &status,
5337                         NULL);
5338
5339         TALLOC_FREE(br_lck);
5340
5341         if (NT_STATUS_V(status)) {
5342                 reply_nterror(req, status);
5343                 END_PROFILE(SMBlock);
5344                 return;
5345         }
5346
5347         reply_outbuf(req, 0, 0);
5348
5349         END_PROFILE(SMBlock);
5350         return;
5351 }
5352
5353 /****************************************************************************
5354  Reply to a unlock.
5355 ****************************************************************************/
5356
5357 void reply_unlock(struct smb_request *req)
5358 {
5359         connection_struct *conn = req->conn;
5360         uint64_t count,offset;
5361         NTSTATUS status;
5362         files_struct *fsp;
5363
5364         START_PROFILE(SMBunlock);
5365
5366         if (req->wct < 5) {
5367                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5368                 END_PROFILE(SMBunlock);
5369                 return;
5370         }
5371
5372         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5373
5374         if (!check_fsp(conn, req, fsp)) {
5375                 END_PROFILE(SMBunlock);
5376                 return;
5377         }
5378
5379         count = (uint64_t)IVAL(req->vwv+1, 0);
5380         offset = (uint64_t)IVAL(req->vwv+3, 0);
5381
5382         status = do_unlock(req->sconn->msg_ctx,
5383                         fsp,
5384                         (uint64_t)req->smbpid,
5385                         count,
5386                         offset,
5387                         WINDOWS_LOCK);
5388
5389         if (NT_STATUS_V(status)) {
5390                 reply_nterror(req, status);
5391                 END_PROFILE(SMBunlock);
5392                 return;
5393         }
5394
5395         DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5396                     fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5397
5398         reply_outbuf(req, 0, 0);
5399
5400         END_PROFILE(SMBunlock);
5401         return;
5402 }
5403
5404 #undef DBGC_CLASS
5405 #define DBGC_CLASS DBGC_ALL
5406
5407 /****************************************************************************
5408  Reply to a tdis.
5409  conn POINTER CAN BE NULL HERE !
5410 ****************************************************************************/
5411
5412 void reply_tdis(struct smb_request *req)
5413 {
5414         NTSTATUS status;
5415         connection_struct *conn = req->conn;
5416         struct smbXsrv_tcon *tcon;
5417
5418         START_PROFILE(SMBtdis);
5419
5420         if (!conn) {
5421                 DEBUG(4,("Invalid connection in tdis\n"));
5422                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5423                 END_PROFILE(SMBtdis);
5424                 return;
5425         }
5426
5427         tcon = conn->tcon;
5428         req->conn = NULL;
5429
5430         /*
5431          * TODO: cancel all outstanding requests on the tcon
5432          */
5433         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5434         if (!NT_STATUS_IS_OK(status)) {
5435                 DEBUG(0, ("reply_tdis: "
5436                           "smbXsrv_tcon_disconnect() failed: %s\n",
5437                           nt_errstr(status)));
5438                 /*
5439                  * If we hit this case, there is something completely
5440                  * wrong, so we better disconnect the transport connection.
5441                  */
5442                 END_PROFILE(SMBtdis);
5443                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5444                 return;
5445         }
5446
5447         TALLOC_FREE(tcon);
5448
5449         reply_outbuf(req, 0, 0);
5450         END_PROFILE(SMBtdis);
5451         return;
5452 }
5453
5454 /****************************************************************************
5455  Reply to a echo.
5456  conn POINTER CAN BE NULL HERE !
5457 ****************************************************************************/
5458
5459 void reply_echo(struct smb_request *req)
5460 {
5461         connection_struct *conn = req->conn;
5462         struct smb_perfcount_data local_pcd;
5463         struct smb_perfcount_data *cur_pcd;
5464         int smb_reverb;
5465         int seq_num;
5466
5467         START_PROFILE(SMBecho);
5468
5469         smb_init_perfcount_data(&local_pcd);
5470
5471         if (req->wct < 1) {
5472                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5473                 END_PROFILE(SMBecho);
5474                 return;
5475         }
5476
5477         smb_reverb = SVAL(req->vwv+0, 0);
5478
5479         reply_outbuf(req, 1, req->buflen);
5480
5481         /* copy any incoming data back out */
5482         if (req->buflen > 0) {
5483                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5484         }
5485
5486         if (smb_reverb > 100) {
5487                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5488                 smb_reverb = 100;
5489         }
5490
5491         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5492
5493                 /* this makes sure we catch the request pcd */
5494                 if (seq_num == smb_reverb) {
5495                         cur_pcd = &req->pcd;
5496                 } else {
5497                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5498                         cur_pcd = &local_pcd;
5499                 }
5500
5501                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5502
5503                 show_msg((char *)req->outbuf);
5504                 if (!srv_send_smb(req->sconn,
5505                                 (char *)req->outbuf,
5506                                 true, req->seqnum+1,
5507                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5508                                 cur_pcd))
5509                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5510         }
5511
5512         DEBUG(3,("echo %d times\n", smb_reverb));
5513
5514         TALLOC_FREE(req->outbuf);
5515
5516         END_PROFILE(SMBecho);
5517         return;
5518 }
5519
5520 /****************************************************************************
5521  Reply to a printopen.
5522 ****************************************************************************/
5523
5524 void reply_printopen(struct smb_request *req)
5525 {
5526         connection_struct *conn = req->conn;
5527         files_struct *fsp;
5528         NTSTATUS status;
5529
5530         START_PROFILE(SMBsplopen);
5531
5532         if (req->wct < 2) {
5533                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5534                 END_PROFILE(SMBsplopen);
5535                 return;
5536         }
5537
5538         if (!CAN_PRINT(conn)) {
5539                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5540                 END_PROFILE(SMBsplopen);
5541                 return;
5542         }
5543
5544         status = file_new(req, conn, &fsp);
5545         if(!NT_STATUS_IS_OK(status)) {
5546                 reply_nterror(req, status);
5547                 END_PROFILE(SMBsplopen);
5548                 return;
5549         }
5550
5551         /* Open for exclusive use, write only. */
5552         status = print_spool_open(fsp, NULL, req->vuid);
5553
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 file_free(req, fsp);
5556                 reply_nterror(req, status);
5557                 END_PROFILE(SMBsplopen);
5558                 return;
5559         }
5560
5561         reply_outbuf(req, 1, 0);
5562         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5563
5564         DEBUG(3,("openprint fd=%d %s\n",
5565                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5566
5567         END_PROFILE(SMBsplopen);
5568         return;
5569 }
5570
5571 /****************************************************************************
5572  Reply to a printclose.
5573 ****************************************************************************/
5574
5575 void reply_printclose(struct smb_request *req)
5576 {
5577         connection_struct *conn = req->conn;
5578         files_struct *fsp;
5579         NTSTATUS status;
5580
5581         START_PROFILE(SMBsplclose);
5582
5583         if (req->wct < 1) {
5584                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5585                 END_PROFILE(SMBsplclose);
5586                 return;
5587         }
5588
5589         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5590
5591         if (!check_fsp(conn, req, fsp)) {
5592                 END_PROFILE(SMBsplclose);
5593                 return;
5594         }
5595
5596         if (!CAN_PRINT(conn)) {
5597                 reply_force_doserror(req, ERRSRV, ERRerror);
5598                 END_PROFILE(SMBsplclose);
5599                 return;
5600         }
5601
5602         DEBUG(3,("printclose fd=%d %s\n",
5603                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5604
5605         status = close_file(req, fsp, NORMAL_CLOSE);
5606
5607         if(!NT_STATUS_IS_OK(status)) {
5608                 reply_nterror(req, status);
5609                 END_PROFILE(SMBsplclose);
5610                 return;
5611         }
5612
5613         reply_outbuf(req, 0, 0);
5614
5615         END_PROFILE(SMBsplclose);
5616         return;
5617 }
5618
5619 /****************************************************************************
5620  Reply to a printqueue.
5621 ****************************************************************************/
5622
5623 void reply_printqueue(struct smb_request *req)
5624 {
5625         connection_struct *conn = req->conn;
5626         int max_count;
5627         int start_index;
5628
5629         START_PROFILE(SMBsplretq);
5630
5631         if (req->wct < 2) {
5632                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5633                 END_PROFILE(SMBsplretq);
5634                 return;
5635         }
5636
5637         max_count = SVAL(req->vwv+0, 0);
5638         start_index = SVAL(req->vwv+1, 0);
5639
5640         /* we used to allow the client to get the cnum wrong, but that
5641            is really quite gross and only worked when there was only
5642            one printer - I think we should now only accept it if they
5643            get it right (tridge) */
5644         if (!CAN_PRINT(conn)) {
5645                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5646                 END_PROFILE(SMBsplretq);
5647                 return;
5648         }
5649
5650         reply_outbuf(req, 2, 3);
5651         SSVAL(req->outbuf,smb_vwv0,0);
5652         SSVAL(req->outbuf,smb_vwv1,0);
5653         SCVAL(smb_buf(req->outbuf),0,1);
5654         SSVAL(smb_buf(req->outbuf),1,0);
5655
5656         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5657                  start_index, max_count));
5658
5659         {
5660                 TALLOC_CTX *mem_ctx = talloc_tos();
5661                 NTSTATUS status;
5662                 WERROR werr;
5663                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5664                 struct rpc_pipe_client *cli = NULL;
5665                 struct dcerpc_binding_handle *b = NULL;
5666                 struct policy_handle handle;
5667                 struct spoolss_DevmodeContainer devmode_ctr;
5668                 union spoolss_JobInfo *info;
5669                 uint32_t count;
5670                 uint32_t num_to_get;
5671                 uint32_t first;
5672                 uint32_t i;
5673
5674                 ZERO_STRUCT(handle);
5675
5676                 status = rpc_pipe_open_interface(conn,
5677                                                  &ndr_table_spoolss,
5678                                                  conn->session_info,
5679                                                  conn->sconn->remote_address,
5680                                                  conn->sconn->msg_ctx,
5681                                                  &cli);
5682                 if (!NT_STATUS_IS_OK(status)) {
5683                         DEBUG(0, ("reply_printqueue: "
5684                                   "could not connect to spoolss: %s\n",
5685                                   nt_errstr(status)));
5686                         reply_nterror(req, status);
5687                         goto out;
5688                 }
5689                 b = cli->binding_handle;
5690
5691                 ZERO_STRUCT(devmode_ctr);
5692
5693                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5694                                                 sharename,
5695                                                 NULL, devmode_ctr,
5696                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5697                                                 &handle,
5698                                                 &werr);
5699                 if (!NT_STATUS_IS_OK(status)) {
5700                         reply_nterror(req, status);
5701                         goto out;
5702                 }
5703                 if (!W_ERROR_IS_OK(werr)) {
5704                         reply_nterror(req, werror_to_ntstatus(werr));
5705                         goto out;
5706                 }
5707
5708                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5709                                                &handle,
5710                                                0, /* firstjob */
5711                                                0xff, /* numjobs */
5712                                                2, /* level */
5713                                                0, /* offered */
5714                                                &count,
5715                                                &info);
5716                 if (!W_ERROR_IS_OK(werr)) {
5717                         reply_nterror(req, werror_to_ntstatus(werr));
5718                         goto out;
5719                 }
5720
5721                 if (max_count > 0) {
5722                         first = start_index;
5723                 } else {
5724                         first = start_index + max_count + 1;
5725                 }
5726
5727                 if (first >= count) {
5728                         num_to_get = first;
5729                 } else {
5730                         num_to_get = first + MIN(ABS(max_count), count - first);
5731                 }
5732
5733                 for (i = first; i < num_to_get; i++) {
5734                         char blob[28];
5735                         char *p = blob;
5736                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5737                         int qstatus;
5738                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5739                                                         info[i].info2.job_id);
5740
5741                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5742                                 qstatus = 2;
5743                         } else {
5744                                 qstatus = 3;
5745                         }
5746
5747                         srv_put_dos_date2(p, 0, qtime);
5748                         SCVAL(p, 4, qstatus);
5749                         SSVAL(p, 5, qrapjobid);
5750                         SIVAL(p, 7, info[i].info2.size);
5751                         SCVAL(p, 11, 0);
5752                         srvstr_push(blob, req->flags2, p+12,
5753                                     info[i].info2.notify_name, 16, STR_ASCII);
5754
5755                         if (message_push_blob(
5756                                     &req->outbuf,
5757                                     data_blob_const(
5758                                             blob, sizeof(blob))) == -1) {
5759                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5760                                 goto out;
5761                         }
5762                 }
5763
5764                 if (count > 0) {
5765                         SSVAL(req->outbuf,smb_vwv0,count);
5766                         SSVAL(req->outbuf,smb_vwv1,
5767                               (max_count>0?first+count:first-1));
5768                         SCVAL(smb_buf(req->outbuf),0,1);
5769                         SSVAL(smb_buf(req->outbuf),1,28*count);
5770                 }
5771
5772
5773                 DEBUG(3, ("%u entries returned in queue\n",
5774                           (unsigned)count));
5775
5776 out:
5777                 if (b && is_valid_policy_hnd(&handle)) {
5778                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5779                 }
5780
5781         }
5782
5783         END_PROFILE(SMBsplretq);
5784         return;
5785 }
5786
5787 /****************************************************************************
5788  Reply to a printwrite.
5789 ****************************************************************************/
5790
5791 void reply_printwrite(struct smb_request *req)
5792 {
5793         connection_struct *conn = req->conn;
5794         int numtowrite;
5795         const char *data;
5796         files_struct *fsp;
5797
5798         START_PROFILE(SMBsplwr);
5799
5800         if (req->wct < 1) {
5801                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5802                 END_PROFILE(SMBsplwr);
5803                 return;
5804         }
5805
5806         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5807
5808         if (!check_fsp(conn, req, fsp)) {
5809                 END_PROFILE(SMBsplwr);
5810                 return;
5811         }
5812
5813         if (!fsp->print_file) {
5814                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5815                 END_PROFILE(SMBsplwr);
5816                 return;
5817         }
5818
5819         if (!CHECK_WRITE(fsp)) {
5820                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5821                 END_PROFILE(SMBsplwr);
5822                 return;
5823         }
5824
5825         numtowrite = SVAL(req->buf, 1);
5826
5827         if (req->buflen < numtowrite + 3) {
5828                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5829                 END_PROFILE(SMBsplwr);
5830                 return;
5831         }
5832
5833         data = (const char *)req->buf + 3;
5834
5835         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5836                 reply_nterror(req, map_nt_error_from_unix(errno));
5837                 END_PROFILE(SMBsplwr);
5838                 return;
5839         }
5840
5841         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5842
5843         END_PROFILE(SMBsplwr);
5844         return;
5845 }
5846
5847 /****************************************************************************
5848  Reply to a mkdir.
5849 ****************************************************************************/
5850
5851 void reply_mkdir(struct smb_request *req)
5852 {
5853         connection_struct *conn = req->conn;
5854         struct smb_filename *smb_dname = NULL;
5855         char *directory = NULL;
5856         NTSTATUS status;
5857         TALLOC_CTX *ctx = talloc_tos();
5858
5859         START_PROFILE(SMBmkdir);
5860
5861         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5862                             STR_TERMINATE, &status);
5863         if (!NT_STATUS_IS_OK(status)) {
5864                 reply_nterror(req, status);
5865                 goto out;
5866         }
5867
5868         status = filename_convert(ctx, conn,
5869                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5870                                  directory,
5871                                  UCF_PREP_CREATEFILE,
5872                                  NULL,
5873                                  &smb_dname);
5874         if (!NT_STATUS_IS_OK(status)) {
5875                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5876                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5877                                         ERRSRV, ERRbadpath);
5878                         goto out;
5879                 }
5880                 reply_nterror(req, status);
5881                 goto out;
5882         }
5883
5884         status = create_directory(conn, req, smb_dname);
5885
5886         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5887
5888         if (!NT_STATUS_IS_OK(status)) {
5889
5890                 if (!use_nt_status()
5891                     && NT_STATUS_EQUAL(status,
5892                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5893                         /*
5894                          * Yes, in the DOS error code case we get a
5895                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5896                          * samba4 torture test.
5897                          */
5898                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5899                 }
5900
5901                 reply_nterror(req, status);
5902                 goto out;
5903         }
5904
5905         reply_outbuf(req, 0, 0);
5906
5907         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5908  out:
5909         TALLOC_FREE(smb_dname);
5910         END_PROFILE(SMBmkdir);
5911         return;
5912 }
5913
5914 /****************************************************************************
5915  Reply to a rmdir.
5916 ****************************************************************************/
5917
5918 void reply_rmdir(struct smb_request *req)
5919 {
5920         connection_struct *conn = req->conn;
5921         struct smb_filename *smb_dname = NULL;
5922         char *directory = NULL;
5923         NTSTATUS status;
5924         TALLOC_CTX *ctx = talloc_tos();
5925         files_struct *fsp = NULL;
5926         int info = 0;
5927         struct smbd_server_connection *sconn = req->sconn;
5928
5929         START_PROFILE(SMBrmdir);
5930
5931         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5932                             STR_TERMINATE, &status);
5933         if (!NT_STATUS_IS_OK(status)) {
5934                 reply_nterror(req, status);
5935                 goto out;
5936         }
5937
5938         status = filename_convert(ctx, conn,
5939                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5940                                  directory,
5941                                  0,
5942                                  NULL,
5943                                  &smb_dname);
5944         if (!NT_STATUS_IS_OK(status)) {
5945                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5946                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5947                                         ERRSRV, ERRbadpath);
5948                         goto out;
5949                 }
5950                 reply_nterror(req, status);
5951                 goto out;
5952         }
5953
5954         if (is_ntfs_stream_smb_fname(smb_dname)) {
5955                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5956                 goto out;
5957         }
5958
5959         status = SMB_VFS_CREATE_FILE(
5960                 conn,                                   /* conn */
5961                 req,                                    /* req */
5962                 0,                                      /* root_dir_fid */
5963                 smb_dname,                              /* fname */
5964                 DELETE_ACCESS,                          /* access_mask */
5965                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5966                         FILE_SHARE_DELETE),
5967                 FILE_OPEN,                              /* create_disposition*/
5968                 FILE_DIRECTORY_FILE,                    /* create_options */
5969                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5970                 0,                                      /* oplock_request */
5971                 0,                                      /* allocation_size */
5972                 0,                                      /* private_flags */
5973                 NULL,                                   /* sd */
5974                 NULL,                                   /* ea_list */
5975                 &fsp,                                   /* result */
5976                 &info);                                 /* pinfo */
5977
5978         if (!NT_STATUS_IS_OK(status)) {
5979                 if (open_was_deferred(req->sconn, req->mid)) {
5980                         /* We have re-scheduled this call. */
5981                         goto out;
5982                 }
5983                 reply_nterror(req, status);
5984                 goto out;
5985         }
5986
5987         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5988         if (!NT_STATUS_IS_OK(status)) {
5989                 close_file(req, fsp, ERROR_CLOSE);
5990                 reply_nterror(req, status);
5991                 goto out;
5992         }
5993
5994         if (!set_delete_on_close(fsp, true,
5995                         conn->session_info->security_token,
5996                         conn->session_info->unix_token)) {
5997                 close_file(req, fsp, ERROR_CLOSE);
5998                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5999                 goto out;
6000         }
6001
6002         status = close_file(req, fsp, NORMAL_CLOSE);
6003         if (!NT_STATUS_IS_OK(status)) {
6004                 reply_nterror(req, status);
6005         } else {
6006                 reply_outbuf(req, 0, 0);
6007         }
6008
6009         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6010
6011         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6012  out:
6013         TALLOC_FREE(smb_dname);
6014         END_PROFILE(SMBrmdir);
6015         return;
6016 }
6017
6018 /*******************************************************************
6019  Resolve wildcards in a filename rename.
6020 ********************************************************************/
6021
6022 static bool resolve_wildcards(TALLOC_CTX *ctx,
6023                                 const char *name1,
6024                                 const char *name2,
6025                                 char **pp_newname)
6026 {
6027         char *name2_copy = NULL;
6028         char *root1 = NULL;
6029         char *root2 = NULL;
6030         char *ext1 = NULL;
6031         char *ext2 = NULL;
6032         char *p,*p2, *pname1, *pname2;
6033
6034         name2_copy = talloc_strdup(ctx, name2);
6035         if (!name2_copy) {
6036                 return False;
6037         }
6038
6039         pname1 = strrchr_m(name1,'/');
6040         pname2 = strrchr_m(name2_copy,'/');
6041
6042         if (!pname1 || !pname2) {
6043                 return False;
6044         }
6045
6046         /* Truncate the copy of name2 at the last '/' */
6047         *pname2 = '\0';
6048
6049         /* Now go past the '/' */
6050         pname1++;
6051         pname2++;
6052
6053         root1 = talloc_strdup(ctx, pname1);
6054         root2 = talloc_strdup(ctx, pname2);
6055
6056         if (!root1 || !root2) {
6057                 return False;
6058         }
6059
6060         p = strrchr_m(root1,'.');
6061         if (p) {
6062                 *p = 0;
6063                 ext1 = talloc_strdup(ctx, p+1);
6064         } else {
6065                 ext1 = talloc_strdup(ctx, "");
6066         }
6067         p = strrchr_m(root2,'.');
6068         if (p) {
6069                 *p = 0;
6070                 ext2 = talloc_strdup(ctx, p+1);
6071         } else {
6072                 ext2 = talloc_strdup(ctx, "");
6073         }
6074
6075         if (!ext1 || !ext2) {
6076                 return False;
6077         }
6078
6079         p = root1;
6080         p2 = root2;
6081         while (*p2) {
6082                 if (*p2 == '?') {
6083                         /* Hmmm. Should this be mb-aware ? */
6084                         *p2 = *p;
6085                         p2++;
6086                 } else if (*p2 == '*') {
6087                         *p2 = '\0';
6088                         root2 = talloc_asprintf(ctx, "%s%s",
6089                                                 root2,
6090                                                 p);
6091                         if (!root2) {
6092                                 return False;
6093                         }
6094                         break;
6095                 } else {
6096                         p2++;
6097                 }
6098                 if (*p) {
6099                         p++;
6100                 }
6101         }
6102
6103         p = ext1;
6104         p2 = ext2;
6105         while (*p2) {
6106                 if (*p2 == '?') {
6107                         /* Hmmm. Should this be mb-aware ? */
6108                         *p2 = *p;
6109                         p2++;
6110                 } else if (*p2 == '*') {
6111                         *p2 = '\0';
6112                         ext2 = talloc_asprintf(ctx, "%s%s",
6113                                                 ext2,
6114                                                 p);
6115                         if (!ext2) {
6116                                 return False;
6117                         }
6118                         break;
6119                 } else {
6120                         p2++;
6121                 }
6122                 if (*p) {
6123                         p++;
6124                 }
6125         }
6126
6127         if (*ext2) {
6128                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6129                                 name2_copy,
6130                                 root2,
6131                                 ext2);
6132         } else {
6133                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6134                                 name2_copy,
6135                                 root2);
6136         }
6137
6138         if (!*pp_newname) {
6139                 return False;
6140         }
6141
6142         return True;
6143 }
6144
6145 /****************************************************************************
6146  Ensure open files have their names updated. Updated to notify other smbd's
6147  asynchronously.
6148 ****************************************************************************/
6149
6150 static void rename_open_files(connection_struct *conn,
6151                               struct share_mode_lock *lck,
6152                               struct file_id id,
6153                               uint32_t orig_name_hash,
6154                               const struct smb_filename *smb_fname_dst)
6155 {
6156         files_struct *fsp;
6157         bool did_rename = False;
6158         NTSTATUS status;
6159         uint32_t new_name_hash = 0;
6160
6161         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6162             fsp = file_find_di_next(fsp)) {
6163                 /* fsp_name is a relative path under the fsp. To change this for other
6164                    sharepaths we need to manipulate relative paths. */
6165                 /* TODO - create the absolute path and manipulate the newname
6166                    relative to the sharepath. */
6167                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6168                         continue;
6169                 }
6170                 if (fsp->name_hash != orig_name_hash) {
6171                         continue;
6172                 }
6173                 DEBUG(10, ("rename_open_files: renaming file %s "
6174                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6175                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6176                            smb_fname_str_dbg(smb_fname_dst)));
6177
6178                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6179                 if (NT_STATUS_IS_OK(status)) {
6180                         did_rename = True;
6181                         new_name_hash = fsp->name_hash;
6182                 }
6183         }
6184
6185         if (!did_rename) {
6186                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6187                            "for %s\n", file_id_string_tos(&id),
6188                            smb_fname_str_dbg(smb_fname_dst)));
6189         }
6190
6191         /* Send messages to all smbd's (not ourself) that the name has changed. */
6192         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6193                               orig_name_hash, new_name_hash,
6194                               smb_fname_dst);
6195
6196 }
6197
6198 /****************************************************************************
6199  We need to check if the source path is a parent directory of the destination
6200  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6201  refuse the rename with a sharing violation. Under UNIX the above call can
6202  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6203  probably need to check that the client is a Windows one before disallowing
6204  this as a UNIX client (one with UNIX extensions) can know the source is a
6205  symlink and make this decision intelligently. Found by an excellent bug
6206  report from <AndyLiebman@aol.com>.
6207 ****************************************************************************/
6208
6209 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6210                                      const struct smb_filename *smb_fname_dst)
6211 {
6212         const char *psrc = smb_fname_src->base_name;
6213         const char *pdst = smb_fname_dst->base_name;
6214         size_t slen;
6215
6216         if (psrc[0] == '.' && psrc[1] == '/') {
6217                 psrc += 2;
6218         }
6219         if (pdst[0] == '.' && pdst[1] == '/') {
6220                 pdst += 2;
6221         }
6222         if ((slen = strlen(psrc)) > strlen(pdst)) {
6223                 return False;
6224         }
6225         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6226 }
6227
6228 /*
6229  * Do the notify calls from a rename
6230  */
6231
6232 static void notify_rename(connection_struct *conn, bool is_dir,
6233                           const struct smb_filename *smb_fname_src,
6234                           const struct smb_filename *smb_fname_dst)
6235 {
6236         char *parent_dir_src = NULL;
6237         char *parent_dir_dst = NULL;
6238         uint32 mask;
6239
6240         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6241                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6242
6243         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6244                             &parent_dir_src, NULL) ||
6245             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6246                             &parent_dir_dst, NULL)) {
6247                 goto out;
6248         }
6249
6250         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6251                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6252                              smb_fname_src->base_name);
6253                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6254                              smb_fname_dst->base_name);
6255         }
6256         else {
6257                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6258                              smb_fname_src->base_name);
6259                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6260                              smb_fname_dst->base_name);
6261         }
6262
6263         /* this is a strange one. w2k3 gives an additional event for
6264            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6265            files, but not directories */
6266         if (!is_dir) {
6267                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6268                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6269                              |FILE_NOTIFY_CHANGE_CREATION,
6270                              smb_fname_dst->base_name);
6271         }
6272  out:
6273         TALLOC_FREE(parent_dir_src);
6274         TALLOC_FREE(parent_dir_dst);
6275 }
6276
6277 /****************************************************************************
6278  Returns an error if the parent directory for a filename is open in an
6279  incompatible way.
6280 ****************************************************************************/
6281
6282 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6283                                         const struct smb_filename *smb_fname_dst_in)
6284 {
6285         char *parent_dir = NULL;
6286         struct smb_filename smb_fname_parent;
6287         struct file_id id;
6288         files_struct *fsp = NULL;
6289         int ret;
6290
6291         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6292                         &parent_dir, NULL)) {
6293                 return NT_STATUS_NO_MEMORY;
6294         }
6295         ZERO_STRUCT(smb_fname_parent);
6296         smb_fname_parent.base_name = parent_dir;
6297
6298         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6299         if (ret == -1) {
6300                 return map_nt_error_from_unix(errno);
6301         }
6302
6303         /*
6304          * We're only checking on this smbd here, mostly good
6305          * enough.. and will pass tests.
6306          */
6307
6308         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6309         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6310                         fsp = file_find_di_next(fsp)) {
6311                 if (fsp->access_mask & DELETE_ACCESS) {
6312                         return NT_STATUS_SHARING_VIOLATION;
6313                 }
6314         }
6315         return NT_STATUS_OK;
6316 }
6317
6318 /****************************************************************************
6319  Rename an open file - given an fsp.
6320 ****************************************************************************/
6321
6322 NTSTATUS rename_internals_fsp(connection_struct *conn,
6323                         files_struct *fsp,
6324                         const struct smb_filename *smb_fname_dst_in,
6325                         uint32 attrs,
6326                         bool replace_if_exists)
6327 {
6328         TALLOC_CTX *ctx = talloc_tos();
6329         struct smb_filename *smb_fname_dst = NULL;
6330         NTSTATUS status = NT_STATUS_OK;
6331         struct share_mode_lock *lck = NULL;
6332         bool dst_exists, old_is_stream, new_is_stream;
6333
6334         status = check_name(conn, smb_fname_dst_in->base_name);
6335         if (!NT_STATUS_IS_OK(status)) {
6336                 return status;
6337         }
6338
6339         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6340         if (!NT_STATUS_IS_OK(status)) {
6341                 return status;
6342         }
6343
6344         /* Make a copy of the dst smb_fname structs */
6345
6346         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6347         if (smb_fname_dst == NULL) {
6348                 status = NT_STATUS_NO_MEMORY;
6349                 goto out;
6350         }
6351
6352         /*
6353          * Check for special case with case preserving and not
6354          * case sensitive. If the old last component differs from the original
6355          * last component only by case, then we should allow
6356          * the rename (user is trying to change the case of the
6357          * filename).
6358          */
6359         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6360             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6361             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6362                 char *last_slash;
6363                 char *fname_dst_lcomp_base_mod = NULL;
6364                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6365
6366                 /*
6367                  * Get the last component of the destination name.
6368                  */
6369                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6370                 if (last_slash) {
6371                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6372                 } else {
6373                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6374                 }
6375                 if (!fname_dst_lcomp_base_mod) {
6376                         status = NT_STATUS_NO_MEMORY;
6377                         goto out;
6378                 }
6379
6380                 /*
6381                  * Create an smb_filename struct using the original last
6382                  * component of the destination.
6383                  */
6384                 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6385                         ctx, smb_fname_dst->original_lcomp, NULL);
6386                 if (smb_fname_orig_lcomp == NULL) {
6387                         status = NT_STATUS_NO_MEMORY;
6388                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6389                         goto out;
6390                 }
6391
6392                 /* If the base names only differ by case, use original. */
6393                 if(!strcsequal(fname_dst_lcomp_base_mod,
6394                                smb_fname_orig_lcomp->base_name)) {
6395                         char *tmp;
6396                         /*
6397                          * Replace the modified last component with the
6398                          * original.
6399                          */
6400                         if (last_slash) {
6401                                 *last_slash = '\0'; /* Truncate at the '/' */
6402                                 tmp = talloc_asprintf(smb_fname_dst,
6403                                         "%s/%s",
6404                                         smb_fname_dst->base_name,
6405                                         smb_fname_orig_lcomp->base_name);
6406                         } else {
6407                                 tmp = talloc_asprintf(smb_fname_dst,
6408                                         "%s",
6409                                         smb_fname_orig_lcomp->base_name);
6410                         }
6411                         if (tmp == NULL) {
6412                                 status = NT_STATUS_NO_MEMORY;
6413                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6414                                 TALLOC_FREE(smb_fname_orig_lcomp);
6415                                 goto out;
6416                         }
6417                         TALLOC_FREE(smb_fname_dst->base_name);
6418                         smb_fname_dst->base_name = tmp;
6419                 }
6420
6421                 /* If the stream_names only differ by case, use original. */
6422                 if(!strcsequal(smb_fname_dst->stream_name,
6423                                smb_fname_orig_lcomp->stream_name)) {
6424                         char *tmp = NULL;
6425                         /* Use the original stream. */
6426                         tmp = talloc_strdup(smb_fname_dst,
6427                                             smb_fname_orig_lcomp->stream_name);
6428                         if (tmp == NULL) {
6429                                 status = NT_STATUS_NO_MEMORY;
6430                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6431                                 TALLOC_FREE(smb_fname_orig_lcomp);
6432                                 goto out;
6433                         }
6434                         TALLOC_FREE(smb_fname_dst->stream_name);
6435                         smb_fname_dst->stream_name = tmp;
6436                 }
6437                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6438                 TALLOC_FREE(smb_fname_orig_lcomp);
6439         }
6440
6441         /*
6442          * If the src and dest names are identical - including case,
6443          * don't do the rename, just return success.
6444          */
6445
6446         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6447             strcsequal(fsp->fsp_name->stream_name,
6448                        smb_fname_dst->stream_name)) {
6449                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6450                           "- returning success\n",
6451                           smb_fname_str_dbg(smb_fname_dst)));
6452                 status = NT_STATUS_OK;
6453                 goto out;
6454         }
6455
6456         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6457         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6458
6459         /* Return the correct error code if both names aren't streams. */
6460         if (!old_is_stream && new_is_stream) {
6461                 status = NT_STATUS_OBJECT_NAME_INVALID;
6462                 goto out;
6463         }
6464
6465         if (old_is_stream && !new_is_stream) {
6466                 status = NT_STATUS_INVALID_PARAMETER;
6467                 goto out;
6468         }
6469
6470         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6471
6472         if(!replace_if_exists && dst_exists) {
6473                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6474                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6475                           smb_fname_str_dbg(smb_fname_dst)));
6476                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6477                 goto out;
6478         }
6479
6480         if (dst_exists) {
6481                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6482                     &smb_fname_dst->st);
6483                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6484                                                            fileid);
6485                 /* The file can be open when renaming a stream */
6486                 if (dst_fsp && !new_is_stream) {
6487                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6488                         status = NT_STATUS_ACCESS_DENIED;
6489                         goto out;
6490                 }
6491         }
6492
6493         /* Ensure we have a valid stat struct for the source. */
6494         status = vfs_stat_fsp(fsp);
6495         if (!NT_STATUS_IS_OK(status)) {
6496                 goto out;
6497         }
6498
6499         status = can_rename(conn, fsp, attrs);
6500
6501         if (!NT_STATUS_IS_OK(status)) {
6502                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6503                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6504                           smb_fname_str_dbg(smb_fname_dst)));
6505                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6506                         status = NT_STATUS_ACCESS_DENIED;
6507                 goto out;
6508         }
6509
6510         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6511                 status = NT_STATUS_ACCESS_DENIED;
6512         }
6513
6514         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6515
6516         /*
6517          * We have the file open ourselves, so not being able to get the
6518          * corresponding share mode lock is a fatal error.
6519          */
6520
6521         SMB_ASSERT(lck != NULL);
6522
6523         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6524                 uint32 create_options = fsp->fh->private_options;
6525
6526                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6527                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6528                           smb_fname_str_dbg(smb_fname_dst)));
6529
6530                 if (!fsp->is_directory &&
6531                     !lp_posix_pathnames() &&
6532                     (lp_map_archive(SNUM(conn)) ||
6533                     lp_store_dos_attributes(SNUM(conn)))) {
6534                         /* We must set the archive bit on the newly
6535                            renamed file. */
6536                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6537                                 uint32_t old_dosmode = dos_mode(conn,
6538                                                         smb_fname_dst);
6539                                 file_set_dosmode(conn,
6540                                         smb_fname_dst,
6541                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6542                                         NULL,
6543                                         true);
6544                         }
6545                 }
6546
6547                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6548                               smb_fname_dst);
6549
6550                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6551                                   smb_fname_dst);
6552
6553                 /*
6554                  * A rename acts as a new file create w.r.t. allowing an initial delete
6555                  * on close, probably because in Windows there is a new handle to the
6556                  * new file. If initial delete on close was requested but not
6557                  * originally set, we need to set it here. This is probably not 100% correct,
6558                  * but will work for the CIFSFS client which in non-posix mode
6559                  * depends on these semantics. JRA.
6560                  */
6561
6562                 if (create_options & FILE_DELETE_ON_CLOSE) {
6563                         status = can_set_delete_on_close(fsp, 0);
6564
6565                         if (NT_STATUS_IS_OK(status)) {
6566                                 /* Note that here we set the *inital* delete on close flag,
6567                                  * not the regular one. The magic gets handled in close. */
6568                                 fsp->initial_delete_on_close = True;
6569                         }
6570                 }
6571                 TALLOC_FREE(lck);
6572                 status = NT_STATUS_OK;
6573                 goto out;
6574         }
6575
6576         TALLOC_FREE(lck);
6577
6578         if (errno == ENOTDIR || errno == EISDIR) {
6579                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6580         } else {
6581                 status = map_nt_error_from_unix(errno);
6582         }
6583
6584         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6585                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6586                   smb_fname_str_dbg(smb_fname_dst)));
6587
6588  out:
6589         TALLOC_FREE(smb_fname_dst);
6590
6591         return status;
6592 }
6593
6594 /****************************************************************************
6595  The guts of the rename command, split out so it may be called by the NT SMB
6596  code.
6597 ****************************************************************************/
6598
6599 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6600                         connection_struct *conn,
6601                         struct smb_request *req,
6602                         struct smb_filename *smb_fname_src,
6603                         struct smb_filename *smb_fname_dst,
6604                         uint32 attrs,
6605                         bool replace_if_exists,
6606                         bool src_has_wild,
6607                         bool dest_has_wild,
6608                         uint32_t access_mask)
6609 {
6610         char *fname_src_dir = NULL;
6611         char *fname_src_mask = NULL;
6612         int count=0;
6613         NTSTATUS status = NT_STATUS_OK;
6614         struct smb_Dir *dir_hnd = NULL;
6615         const char *dname = NULL;
6616         char *talloced = NULL;
6617         long offset = 0;
6618         int create_options = 0;
6619         bool posix_pathnames = lp_posix_pathnames();
6620         int rc;
6621
6622         /*
6623          * Split the old name into directory and last component
6624          * strings. Note that unix_convert may have stripped off a
6625          * leading ./ from both name and newname if the rename is
6626          * at the root of the share. We need to make sure either both
6627          * name and newname contain a / character or neither of them do
6628          * as this is checked in resolve_wildcards().
6629          */
6630
6631         /* Split up the directory from the filename/mask. */
6632         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6633                                       &fname_src_dir, &fname_src_mask);
6634         if (!NT_STATUS_IS_OK(status)) {
6635                 status = NT_STATUS_NO_MEMORY;
6636                 goto out;
6637         }
6638
6639         /*
6640          * We should only check the mangled cache
6641          * here if unix_convert failed. This means
6642          * that the path in 'mask' doesn't exist
6643          * on the file system and so we need to look
6644          * for a possible mangle. This patch from
6645          * Tine Smukavec <valentin.smukavec@hermes.si>.
6646          */
6647
6648         if (!VALID_STAT(smb_fname_src->st) &&
6649             mangle_is_mangled(fname_src_mask, conn->params)) {
6650                 char *new_mask = NULL;
6651                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6652                                             conn->params);
6653                 if (new_mask) {
6654                         TALLOC_FREE(fname_src_mask);
6655                         fname_src_mask = new_mask;
6656                 }
6657         }
6658
6659         if (!src_has_wild) {
6660                 files_struct *fsp;
6661
6662                 /*
6663                  * Only one file needs to be renamed. Append the mask back
6664                  * onto the directory.
6665                  */
6666                 TALLOC_FREE(smb_fname_src->base_name);
6667                 if (ISDOT(fname_src_dir)) {
6668                         /* Ensure we use canonical names on open. */
6669                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6670                                                         "%s",
6671                                                         fname_src_mask);
6672                 } else {
6673                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6674                                                         "%s/%s",
6675                                                         fname_src_dir,
6676                                                         fname_src_mask);
6677                 }
6678                 if (!smb_fname_src->base_name) {
6679                         status = NT_STATUS_NO_MEMORY;
6680                         goto out;
6681                 }
6682
6683                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6684                           "case_preserve = %d, short case preserve = %d, "
6685                           "directory = %s, newname = %s, "
6686                           "last_component_dest = %s\n",
6687                           conn->case_sensitive, conn->case_preserve,
6688                           conn->short_case_preserve,
6689                           smb_fname_str_dbg(smb_fname_src),
6690                           smb_fname_str_dbg(smb_fname_dst),
6691                           smb_fname_dst->original_lcomp));
6692
6693                 /* The dest name still may have wildcards. */
6694                 if (dest_has_wild) {
6695                         char *fname_dst_mod = NULL;
6696                         if (!resolve_wildcards(smb_fname_dst,
6697                                                smb_fname_src->base_name,
6698                                                smb_fname_dst->base_name,
6699                                                &fname_dst_mod)) {
6700                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6701                                           "%s %s failed\n",
6702                                           smb_fname_src->base_name,
6703                                           smb_fname_dst->base_name));
6704                                 status = NT_STATUS_NO_MEMORY;
6705                                 goto out;
6706                         }
6707                         TALLOC_FREE(smb_fname_dst->base_name);
6708                         smb_fname_dst->base_name = fname_dst_mod;
6709                 }
6710
6711                 ZERO_STRUCT(smb_fname_src->st);
6712                 if (posix_pathnames) {
6713                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6714                 } else {
6715                         rc = SMB_VFS_STAT(conn, smb_fname_src);
6716                 }
6717                 if (rc == -1) {
6718                         status = map_nt_error_from_unix_common(errno);
6719                         goto out;
6720                 }
6721
6722                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6723                         create_options |= FILE_DIRECTORY_FILE;
6724                 }
6725
6726                 status = SMB_VFS_CREATE_FILE(
6727                         conn,                           /* conn */
6728                         req,                            /* req */
6729                         0,                              /* root_dir_fid */
6730                         smb_fname_src,                  /* fname */
6731                         access_mask,                    /* access_mask */
6732                         (FILE_SHARE_READ |              /* share_access */
6733                             FILE_SHARE_WRITE),
6734                         FILE_OPEN,                      /* create_disposition*/
6735                         create_options,                 /* create_options */
6736                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6737                         0,                              /* oplock_request */
6738                         0,                              /* allocation_size */
6739                         0,                              /* private_flags */
6740                         NULL,                           /* sd */
6741                         NULL,                           /* ea_list */
6742                         &fsp,                           /* result */
6743                         NULL);                          /* pinfo */
6744
6745                 if (!NT_STATUS_IS_OK(status)) {
6746                         DEBUG(3, ("Could not open rename source %s: %s\n",
6747                                   smb_fname_str_dbg(smb_fname_src),
6748                                   nt_errstr(status)));
6749                         goto out;
6750                 }
6751
6752                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6753                                               attrs, replace_if_exists);
6754
6755                 close_file(req, fsp, NORMAL_CLOSE);
6756
6757                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6758                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6759                           smb_fname_str_dbg(smb_fname_dst)));
6760
6761                 goto out;
6762         }
6763
6764         /*
6765          * Wildcards - process each file that matches.
6766          */
6767         if (strequal(fname_src_mask, "????????.???")) {
6768                 TALLOC_FREE(fname_src_mask);
6769                 fname_src_mask = talloc_strdup(ctx, "*");
6770                 if (!fname_src_mask) {
6771                         status = NT_STATUS_NO_MEMORY;
6772                         goto out;
6773                 }
6774         }
6775
6776         status = check_name(conn, fname_src_dir);
6777         if (!NT_STATUS_IS_OK(status)) {
6778                 goto out;
6779         }
6780
6781         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6782                           attrs);
6783         if (dir_hnd == NULL) {
6784                 status = map_nt_error_from_unix(errno);
6785                 goto out;
6786         }
6787
6788         status = NT_STATUS_NO_SUCH_FILE;
6789         /*
6790          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6791          * - gentest fix. JRA
6792          */
6793
6794         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6795                                     &talloced))) {
6796                 files_struct *fsp = NULL;
6797                 char *destname = NULL;
6798                 bool sysdir_entry = False;
6799
6800                 /* Quick check for "." and ".." */
6801                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6802                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6803                                 sysdir_entry = True;
6804                         } else {
6805                                 TALLOC_FREE(talloced);
6806                                 continue;
6807                         }
6808                 }
6809
6810                 if (!is_visible_file(conn, fname_src_dir, dname,
6811                                      &smb_fname_src->st, false)) {
6812                         TALLOC_FREE(talloced);
6813                         continue;
6814                 }
6815
6816                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6817                         TALLOC_FREE(talloced);
6818                         continue;
6819                 }
6820
6821                 if (sysdir_entry) {
6822                         status = NT_STATUS_OBJECT_NAME_INVALID;
6823                         break;
6824                 }
6825
6826                 TALLOC_FREE(smb_fname_src->base_name);
6827                 if (ISDOT(fname_src_dir)) {
6828                         /* Ensure we use canonical names on open. */
6829                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6830                                                         "%s",
6831                                                         dname);
6832                 } else {
6833                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6834                                                         "%s/%s",
6835                                                         fname_src_dir,
6836                                                         dname);
6837                 }
6838                 if (!smb_fname_src->base_name) {
6839                         status = NT_STATUS_NO_MEMORY;
6840                         goto out;
6841                 }
6842
6843                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6844                                        smb_fname_dst->base_name,
6845                                        &destname)) {
6846                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6847                                   smb_fname_src->base_name, destname));
6848                         TALLOC_FREE(talloced);
6849                         continue;
6850                 }
6851                 if (!destname) {
6852                         status = NT_STATUS_NO_MEMORY;
6853                         goto out;
6854                 }
6855
6856                 TALLOC_FREE(smb_fname_dst->base_name);
6857                 smb_fname_dst->base_name = destname;
6858
6859                 ZERO_STRUCT(smb_fname_src->st);
6860                 if (posix_pathnames) {
6861                         SMB_VFS_LSTAT(conn, smb_fname_src);
6862                 } else {
6863                         SMB_VFS_STAT(conn, smb_fname_src);
6864                 }
6865
6866                 create_options = 0;
6867
6868                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6869                         create_options |= FILE_DIRECTORY_FILE;
6870                 }
6871
6872                 status = SMB_VFS_CREATE_FILE(
6873                         conn,                           /* conn */
6874                         req,                            /* req */
6875                         0,                              /* root_dir_fid */
6876                         smb_fname_src,                  /* fname */
6877                         access_mask,                    /* access_mask */
6878                         (FILE_SHARE_READ |              /* share_access */
6879                             FILE_SHARE_WRITE),
6880                         FILE_OPEN,                      /* create_disposition*/
6881                         create_options,                 /* create_options */
6882                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6883                         0,                              /* oplock_request */
6884                         0,                              /* allocation_size */
6885                         0,                              /* private_flags */
6886                         NULL,                           /* sd */
6887                         NULL,                           /* ea_list */
6888                         &fsp,                           /* result */
6889                         NULL);                          /* pinfo */
6890
6891                 if (!NT_STATUS_IS_OK(status)) {
6892                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6893                                  "returned %s rename %s -> %s\n",
6894                                  nt_errstr(status),
6895                                  smb_fname_str_dbg(smb_fname_src),
6896                                  smb_fname_str_dbg(smb_fname_dst)));
6897                         break;
6898                 }
6899
6900                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6901                                                               dname);
6902                 if (!smb_fname_dst->original_lcomp) {
6903                         status = NT_STATUS_NO_MEMORY;
6904                         goto out;
6905                 }
6906
6907                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6908                                               attrs, replace_if_exists);
6909
6910                 close_file(req, fsp, NORMAL_CLOSE);
6911
6912                 if (!NT_STATUS_IS_OK(status)) {
6913                         DEBUG(3, ("rename_internals_fsp returned %s for "
6914                                   "rename %s -> %s\n", nt_errstr(status),
6915                                   smb_fname_str_dbg(smb_fname_src),
6916                                   smb_fname_str_dbg(smb_fname_dst)));
6917                         break;
6918                 }
6919
6920                 count++;
6921
6922                 DEBUG(3,("rename_internals: doing rename on %s -> "
6923                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6924                          smb_fname_str_dbg(smb_fname_src)));
6925                 TALLOC_FREE(talloced);
6926         }
6927         TALLOC_FREE(dir_hnd);
6928
6929         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6930                 status = map_nt_error_from_unix(errno);
6931         }
6932
6933  out:
6934         TALLOC_FREE(talloced);
6935         TALLOC_FREE(fname_src_dir);
6936         TALLOC_FREE(fname_src_mask);
6937         return status;
6938 }
6939
6940 /****************************************************************************
6941  Reply to a mv.
6942 ****************************************************************************/
6943
6944 void reply_mv(struct smb_request *req)
6945 {
6946         connection_struct *conn = req->conn;
6947         char *name = NULL;
6948         char *newname = NULL;
6949         const char *p;
6950         uint32 attrs;
6951         NTSTATUS status;
6952         bool src_has_wcard = False;
6953         bool dest_has_wcard = False;
6954         TALLOC_CTX *ctx = talloc_tos();
6955         struct smb_filename *smb_fname_src = NULL;
6956         struct smb_filename *smb_fname_dst = NULL;
6957         uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6958         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6959         bool stream_rename = false;
6960
6961         START_PROFILE(SMBmv);
6962
6963         if (req->wct < 1) {
6964                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6965                 goto out;
6966         }
6967
6968         attrs = SVAL(req->vwv+0, 0);
6969
6970         p = (const char *)req->buf + 1;
6971         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6972                                        &status, &src_has_wcard);
6973         if (!NT_STATUS_IS_OK(status)) {
6974                 reply_nterror(req, status);
6975                 goto out;
6976         }
6977         p++;
6978         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6979                                        &status, &dest_has_wcard);
6980         if (!NT_STATUS_IS_OK(status)) {
6981                 reply_nterror(req, status);
6982                 goto out;
6983         }
6984
6985         if (!lp_posix_pathnames()) {
6986                 /* The newname must begin with a ':' if the
6987                    name contains a ':'. */
6988                 if (strchr_m(name, ':')) {
6989                         if (newname[0] != ':') {
6990                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6991                                 goto out;
6992                         }
6993                         stream_rename = true;
6994                 }
6995         }
6996
6997         status = filename_convert(ctx,
6998                                   conn,
6999                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7000                                   name,
7001                                   src_ucf_flags,
7002                                   &src_has_wcard,
7003                                   &smb_fname_src);
7004
7005         if (!NT_STATUS_IS_OK(status)) {
7006                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7007                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7008                                         ERRSRV, ERRbadpath);
7009                         goto out;
7010                 }
7011                 reply_nterror(req, status);
7012                 goto out;
7013         }
7014
7015         status = filename_convert(ctx,
7016                                   conn,
7017                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7018                                   newname,
7019                                   dst_ucf_flags,
7020                                   &dest_has_wcard,
7021                                   &smb_fname_dst);
7022
7023         if (!NT_STATUS_IS_OK(status)) {
7024                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7025                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7026                                         ERRSRV, ERRbadpath);
7027                         goto out;
7028                 }
7029                 reply_nterror(req, status);
7030                 goto out;
7031         }
7032
7033         if (stream_rename) {
7034                 /* smb_fname_dst->base_name must be the same as
7035                    smb_fname_src->base_name. */
7036                 TALLOC_FREE(smb_fname_dst->base_name);
7037                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7038                                                 smb_fname_src->base_name);
7039                 if (!smb_fname_dst->base_name) {
7040                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7041                         goto out;
7042                 }
7043         }
7044
7045         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7046                  smb_fname_str_dbg(smb_fname_dst)));
7047
7048         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7049                                   attrs, False, src_has_wcard, dest_has_wcard,
7050                                   DELETE_ACCESS);
7051         if (!NT_STATUS_IS_OK(status)) {
7052                 if (open_was_deferred(req->sconn, req->mid)) {
7053                         /* We have re-scheduled this call. */
7054                         goto out;
7055                 }
7056                 reply_nterror(req, status);
7057                 goto out;
7058         }
7059
7060         reply_outbuf(req, 0, 0);
7061  out:
7062         TALLOC_FREE(smb_fname_src);
7063         TALLOC_FREE(smb_fname_dst);
7064         END_PROFILE(SMBmv);
7065         return;
7066 }
7067
7068 /*******************************************************************
7069  Copy a file as part of a reply_copy.
7070 ******************************************************************/
7071
7072 /*
7073  * TODO: check error codes on all callers
7074  */
7075
7076 NTSTATUS copy_file(TALLOC_CTX *ctx,
7077                         connection_struct *conn,
7078                         struct smb_filename *smb_fname_src,
7079                         struct smb_filename *smb_fname_dst,
7080                         int ofun,
7081                         int count,
7082                         bool target_is_directory)
7083 {
7084         struct smb_filename *smb_fname_dst_tmp = NULL;
7085         off_t ret=-1;
7086         files_struct *fsp1,*fsp2;
7087         uint32 dosattrs;
7088         uint32 new_create_disposition;
7089         NTSTATUS status;
7090
7091
7092         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7093         if (smb_fname_dst_tmp == NULL) {
7094                 return NT_STATUS_NO_MEMORY;
7095         }
7096
7097         /*
7098          * If the target is a directory, extract the last component from the
7099          * src filename and append it to the dst filename
7100          */
7101         if (target_is_directory) {
7102                 const char *p;
7103
7104                 /* dest/target can't be a stream if it's a directory. */
7105                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7106
7107                 p = strrchr_m(smb_fname_src->base_name,'/');
7108                 if (p) {
7109                         p++;
7110                 } else {
7111                         p = smb_fname_src->base_name;
7112                 }
7113                 smb_fname_dst_tmp->base_name =
7114                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7115                                            p);
7116                 if (!smb_fname_dst_tmp->base_name) {
7117                         status = NT_STATUS_NO_MEMORY;
7118                         goto out;
7119                 }
7120         }
7121
7122         status = vfs_file_exist(conn, smb_fname_src);
7123         if (!NT_STATUS_IS_OK(status)) {
7124                 goto out;
7125         }
7126
7127         if (!target_is_directory && count) {
7128                 new_create_disposition = FILE_OPEN;
7129         } else {
7130                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7131                                                  0, ofun,
7132                                                  NULL, NULL,
7133                                                  &new_create_disposition,
7134                                                  NULL,
7135                                                  NULL)) {
7136                         status = NT_STATUS_INVALID_PARAMETER;
7137                         goto out;
7138                 }
7139         }
7140
7141         /* Open the src file for reading. */
7142         status = SMB_VFS_CREATE_FILE(
7143                 conn,                                   /* conn */
7144                 NULL,                                   /* req */
7145                 0,                                      /* root_dir_fid */
7146                 smb_fname_src,                          /* fname */
7147                 FILE_GENERIC_READ,                      /* access_mask */
7148                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7149                 FILE_OPEN,                              /* create_disposition*/
7150                 0,                                      /* create_options */
7151                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7152                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7153                 0,                                      /* allocation_size */
7154                 0,                                      /* private_flags */
7155                 NULL,                                   /* sd */
7156                 NULL,                                   /* ea_list */
7157                 &fsp1,                                  /* result */
7158                 NULL);                                  /* psbuf */
7159
7160         if (!NT_STATUS_IS_OK(status)) {
7161                 goto out;
7162         }
7163
7164         dosattrs = dos_mode(conn, smb_fname_src);
7165
7166         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7167                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7168         }
7169
7170         /* Open the dst file for writing. */
7171         status = SMB_VFS_CREATE_FILE(
7172                 conn,                                   /* conn */
7173                 NULL,                                   /* req */
7174                 0,                                      /* root_dir_fid */
7175                 smb_fname_dst,                          /* fname */
7176                 FILE_GENERIC_WRITE,                     /* access_mask */
7177                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7178                 new_create_disposition,                 /* create_disposition*/
7179                 0,                                      /* create_options */
7180                 dosattrs,                               /* file_attributes */
7181                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7182                 0,                                      /* allocation_size */
7183                 0,                                      /* private_flags */
7184                 NULL,                                   /* sd */
7185                 NULL,                                   /* ea_list */
7186                 &fsp2,                                  /* result */
7187                 NULL);                                  /* psbuf */
7188
7189         if (!NT_STATUS_IS_OK(status)) {
7190                 close_file(NULL, fsp1, ERROR_CLOSE);
7191                 goto out;
7192         }
7193
7194         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7195                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7196                 if (ret == -1) {
7197                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7198                                 strerror(errno)));
7199                         status = map_nt_error_from_unix(errno);
7200                         close_file(NULL, fsp1, ERROR_CLOSE);
7201                         close_file(NULL, fsp2, ERROR_CLOSE);
7202                         goto out;
7203                 }
7204         }
7205
7206         /* Do the actual copy. */
7207         if (smb_fname_src->st.st_ex_size) {
7208                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7209         } else {
7210                 ret = 0;
7211         }
7212
7213         close_file(NULL, fsp1, NORMAL_CLOSE);
7214
7215         /* Ensure the modtime is set correctly on the destination file. */
7216         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7217
7218         /*
7219          * As we are opening fsp1 read-only we only expect
7220          * an error on close on fsp2 if we are out of space.
7221          * Thus we don't look at the error return from the
7222          * close of fsp1.
7223          */
7224         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7225
7226         if (!NT_STATUS_IS_OK(status)) {
7227                 goto out;
7228         }
7229
7230         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7231                 status = NT_STATUS_DISK_FULL;
7232                 goto out;
7233         }
7234
7235         status = NT_STATUS_OK;
7236
7237  out:
7238         TALLOC_FREE(smb_fname_dst_tmp);
7239         return status;
7240 }
7241
7242 /****************************************************************************
7243  Reply to a file copy.
7244 ****************************************************************************/
7245
7246 void reply_copy(struct smb_request *req)
7247 {
7248         connection_struct *conn = req->conn;
7249         struct smb_filename *smb_fname_src = NULL;
7250         struct smb_filename *smb_fname_dst = NULL;
7251         char *fname_src = NULL;
7252         char *fname_dst = NULL;
7253         char *fname_src_mask = NULL;
7254         char *fname_src_dir = NULL;
7255         const char *p;
7256         int count=0;
7257         int error = ERRnoaccess;
7258         int tid2;
7259         int ofun;
7260         int flags;
7261         bool target_is_directory=False;
7262         bool source_has_wild = False;
7263         bool dest_has_wild = False;
7264         NTSTATUS status;
7265         TALLOC_CTX *ctx = talloc_tos();
7266
7267         START_PROFILE(SMBcopy);
7268
7269         if (req->wct < 3) {
7270                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7271                 goto out;
7272         }
7273
7274         tid2 = SVAL(req->vwv+0, 0);
7275         ofun = SVAL(req->vwv+1, 0);
7276         flags = SVAL(req->vwv+2, 0);
7277
7278         p = (const char *)req->buf;
7279         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7280                                        &status, &source_has_wild);
7281         if (!NT_STATUS_IS_OK(status)) {
7282                 reply_nterror(req, status);
7283                 goto out;
7284         }
7285         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7286                                        &status, &dest_has_wild);
7287         if (!NT_STATUS_IS_OK(status)) {
7288                 reply_nterror(req, status);
7289                 goto out;
7290         }
7291
7292         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7293
7294         if (tid2 != conn->cnum) {
7295                 /* can't currently handle inter share copies XXXX */
7296                 DEBUG(3,("Rejecting inter-share copy\n"));
7297                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7298                 goto out;
7299         }
7300
7301         status = filename_convert(ctx, conn,
7302                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7303                                   fname_src,
7304                                   UCF_COND_ALLOW_WCARD_LCOMP,
7305                                   &source_has_wild,
7306                                   &smb_fname_src);
7307         if (!NT_STATUS_IS_OK(status)) {
7308                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7309                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7310                                         ERRSRV, ERRbadpath);
7311                         goto out;
7312                 }
7313                 reply_nterror(req, status);
7314                 goto out;
7315         }
7316
7317         status = filename_convert(ctx, conn,
7318                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7319                                   fname_dst,
7320                                   UCF_COND_ALLOW_WCARD_LCOMP,
7321                                   &dest_has_wild,
7322                                   &smb_fname_dst);
7323         if (!NT_STATUS_IS_OK(status)) {
7324                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7325                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7326                                         ERRSRV, ERRbadpath);
7327                         goto out;
7328                 }
7329                 reply_nterror(req, status);
7330                 goto out;
7331         }
7332
7333         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7334
7335         if ((flags&1) && target_is_directory) {
7336                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7337                 goto out;
7338         }
7339
7340         if ((flags&2) && !target_is_directory) {
7341                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7342                 goto out;
7343         }
7344
7345         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7346                 /* wants a tree copy! XXXX */
7347                 DEBUG(3,("Rejecting tree copy\n"));
7348                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7349                 goto out;
7350         }
7351
7352         /* Split up the directory from the filename/mask. */
7353         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7354                                       &fname_src_dir, &fname_src_mask);
7355         if (!NT_STATUS_IS_OK(status)) {
7356                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7357                 goto out;
7358         }
7359
7360         /*
7361          * We should only check the mangled cache
7362          * here if unix_convert failed. This means
7363          * that the path in 'mask' doesn't exist
7364          * on the file system and so we need to look
7365          * for a possible mangle. This patch from
7366          * Tine Smukavec <valentin.smukavec@hermes.si>.
7367          */
7368         if (!VALID_STAT(smb_fname_src->st) &&
7369             mangle_is_mangled(fname_src_mask, conn->params)) {
7370                 char *new_mask = NULL;
7371                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7372                                             &new_mask, conn->params);
7373
7374                 /* Use demangled name if one was successfully found. */
7375                 if (new_mask) {
7376                         TALLOC_FREE(fname_src_mask);
7377                         fname_src_mask = new_mask;
7378                 }
7379         }
7380
7381         if (!source_has_wild) {
7382
7383                 /*
7384                  * Only one file needs to be copied. Append the mask back onto
7385                  * the directory.
7386                  */
7387                 TALLOC_FREE(smb_fname_src->base_name);
7388                 if (ISDOT(fname_src_dir)) {
7389                         /* Ensure we use canonical names on open. */
7390                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7391                                                         "%s",
7392                                                         fname_src_mask);
7393                 } else {
7394                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7395                                                         "%s/%s",
7396                                                         fname_src_dir,
7397                                                         fname_src_mask);
7398                 }
7399                 if (!smb_fname_src->base_name) {
7400                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7401                         goto out;
7402                 }
7403
7404                 if (dest_has_wild) {
7405                         char *fname_dst_mod = NULL;
7406                         if (!resolve_wildcards(smb_fname_dst,
7407                                                smb_fname_src->base_name,
7408                                                smb_fname_dst->base_name,
7409                                                &fname_dst_mod)) {
7410                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7411                                 goto out;
7412                         }
7413                         TALLOC_FREE(smb_fname_dst->base_name);
7414                         smb_fname_dst->base_name = fname_dst_mod;
7415                 }
7416
7417                 status = check_name(conn, smb_fname_src->base_name);
7418                 if (!NT_STATUS_IS_OK(status)) {
7419                         reply_nterror(req, status);
7420                         goto out;
7421                 }
7422
7423                 status = check_name(conn, smb_fname_dst->base_name);
7424                 if (!NT_STATUS_IS_OK(status)) {
7425                         reply_nterror(req, status);
7426                         goto out;
7427                 }
7428
7429                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7430                                    ofun, count, target_is_directory);
7431
7432                 if(!NT_STATUS_IS_OK(status)) {
7433                         reply_nterror(req, status);
7434                         goto out;
7435                 } else {
7436                         count++;
7437                 }
7438         } else {
7439                 struct smb_Dir *dir_hnd = NULL;
7440                 const char *dname = NULL;
7441                 char *talloced = NULL;
7442                 long offset = 0;
7443
7444                 /*
7445                  * There is a wildcard that requires us to actually read the
7446                  * src dir and copy each file matching the mask to the dst.
7447                  * Right now streams won't be copied, but this could
7448                  * presumably be added with a nested loop for reach dir entry.
7449                  */
7450                 SMB_ASSERT(!smb_fname_src->stream_name);
7451                 SMB_ASSERT(!smb_fname_dst->stream_name);
7452
7453                 smb_fname_src->stream_name = NULL;
7454                 smb_fname_dst->stream_name = NULL;
7455
7456                 if (strequal(fname_src_mask,"????????.???")) {
7457                         TALLOC_FREE(fname_src_mask);
7458                         fname_src_mask = talloc_strdup(ctx, "*");
7459                         if (!fname_src_mask) {
7460                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7461                                 goto out;
7462                         }
7463                 }
7464
7465                 status = check_name(conn, fname_src_dir);
7466                 if (!NT_STATUS_IS_OK(status)) {
7467                         reply_nterror(req, status);
7468                         goto out;
7469                 }
7470
7471                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7472                 if (dir_hnd == NULL) {
7473                         status = map_nt_error_from_unix(errno);
7474                         reply_nterror(req, status);
7475                         goto out;
7476                 }
7477
7478                 error = ERRbadfile;
7479
7480                 /* Iterate over the src dir copying each entry to the dst. */
7481                 while ((dname = ReadDirName(dir_hnd, &offset,
7482                                             &smb_fname_src->st, &talloced))) {
7483                         char *destname = NULL;
7484
7485                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7486                                 TALLOC_FREE(talloced);
7487                                 continue;
7488                         }
7489
7490                         if (!is_visible_file(conn, fname_src_dir, dname,
7491                                              &smb_fname_src->st, false)) {
7492                                 TALLOC_FREE(talloced);
7493                                 continue;
7494                         }
7495
7496                         if(!mask_match(dname, fname_src_mask,
7497                                        conn->case_sensitive)) {
7498                                 TALLOC_FREE(talloced);
7499                                 continue;
7500                         }
7501
7502                         error = ERRnoaccess;
7503
7504                         /* Get the src smb_fname struct setup. */
7505                         TALLOC_FREE(smb_fname_src->base_name);
7506                         if (ISDOT(fname_src_dir)) {
7507                                 /* Ensure we use canonical names on open. */
7508                                 smb_fname_src->base_name =
7509                                         talloc_asprintf(smb_fname_src, "%s",
7510                                                 dname);
7511                         } else {
7512                                 smb_fname_src->base_name =
7513                                         talloc_asprintf(smb_fname_src, "%s/%s",
7514                                                 fname_src_dir, dname);
7515                         }
7516
7517                         if (!smb_fname_src->base_name) {
7518                                 TALLOC_FREE(dir_hnd);
7519                                 TALLOC_FREE(talloced);
7520                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7521                                 goto out;
7522                         }
7523
7524                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7525                                                smb_fname_dst->base_name,
7526                                                &destname)) {
7527                                 TALLOC_FREE(talloced);
7528                                 continue;
7529                         }
7530                         if (!destname) {
7531                                 TALLOC_FREE(dir_hnd);
7532                                 TALLOC_FREE(talloced);
7533                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7534                                 goto out;
7535                         }
7536
7537                         TALLOC_FREE(smb_fname_dst->base_name);
7538                         smb_fname_dst->base_name = destname;
7539
7540                         status = check_name(conn, smb_fname_src->base_name);
7541                         if (!NT_STATUS_IS_OK(status)) {
7542                                 TALLOC_FREE(dir_hnd);
7543                                 TALLOC_FREE(talloced);
7544                                 reply_nterror(req, status);
7545                                 goto out;
7546                         }
7547
7548                         status = check_name(conn, smb_fname_dst->base_name);
7549                         if (!NT_STATUS_IS_OK(status)) {
7550                                 TALLOC_FREE(dir_hnd);
7551                                 TALLOC_FREE(talloced);
7552                                 reply_nterror(req, status);
7553                                 goto out;
7554                         }
7555
7556                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7557                                 smb_fname_src->base_name,
7558                                 smb_fname_dst->base_name));
7559
7560                         status = copy_file(ctx, conn, smb_fname_src,
7561                                            smb_fname_dst, ofun, count,
7562                                            target_is_directory);
7563                         if (NT_STATUS_IS_OK(status)) {
7564                                 count++;
7565                         }
7566
7567                         TALLOC_FREE(talloced);
7568                 }
7569                 TALLOC_FREE(dir_hnd);
7570         }
7571
7572         if (count == 0) {
7573                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7574                 goto out;
7575         }
7576
7577         reply_outbuf(req, 1, 0);
7578         SSVAL(req->outbuf,smb_vwv0,count);
7579  out:
7580         TALLOC_FREE(smb_fname_src);
7581         TALLOC_FREE(smb_fname_dst);
7582         TALLOC_FREE(fname_src);
7583         TALLOC_FREE(fname_dst);
7584         TALLOC_FREE(fname_src_mask);
7585         TALLOC_FREE(fname_src_dir);
7586
7587         END_PROFILE(SMBcopy);
7588         return;
7589 }
7590
7591 #undef DBGC_CLASS
7592 #define DBGC_CLASS DBGC_LOCKING
7593
7594 /****************************************************************************
7595  Get a lock pid, dealing with large count requests.
7596 ****************************************************************************/
7597
7598 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7599                     bool large_file_format)
7600 {
7601         if(!large_file_format)
7602                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7603         else
7604                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7605 }
7606
7607 /****************************************************************************
7608  Get a lock count, dealing with large count requests.
7609 ****************************************************************************/
7610
7611 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7612                         bool large_file_format)
7613 {
7614         uint64_t count = 0;
7615
7616         if(!large_file_format) {
7617                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7618         } else {
7619                 /*
7620                  * No BVAL, this is reversed!
7621                  */
7622                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7623                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7624         }
7625
7626         return count;
7627 }
7628
7629 /****************************************************************************
7630  Get a lock offset, dealing with large offset requests.
7631 ****************************************************************************/
7632
7633 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7634                          bool large_file_format)
7635 {
7636         uint64_t offset = 0;
7637
7638         if(!large_file_format) {
7639                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7640         } else {
7641                 /*
7642                  * No BVAL, this is reversed!
7643                  */
7644                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7645                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7646         }
7647
7648         return offset;
7649 }
7650
7651 NTSTATUS smbd_do_locking(struct smb_request *req,
7652                          files_struct *fsp,
7653                          uint8_t type,
7654                          int32_t timeout,
7655                          uint16_t num_locks,
7656                          struct smbd_lock_element *locks,
7657                          bool *async)
7658 {
7659         connection_struct *conn = req->conn;
7660         int i;
7661         NTSTATUS status = NT_STATUS_OK;
7662
7663         *async = false;
7664
7665         /* Setup the timeout in seconds. */
7666
7667         if (!lp_blocking_locks(SNUM(conn))) {
7668                 timeout = 0;
7669         }
7670
7671         for(i = 0; i < (int)num_locks; i++) {
7672                 struct smbd_lock_element *e = &locks[i];
7673
7674                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7675                           "%llu, file %s timeout = %d\n",
7676                           (double)e->offset,
7677                           (double)e->count,
7678                           (unsigned long long)e->smblctx,
7679                           fsp_str_dbg(fsp),
7680                           (int)timeout));
7681
7682                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7683                         struct blocking_lock_record *blr = NULL;
7684
7685                         if (num_locks > 1) {
7686                                 /*
7687                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7688                                  * if the lock vector contains one entry. When given multiple cancel
7689                                  * requests in a single PDU we expect the server to return an
7690                                  * error. Windows servers seem to accept the request but only
7691                                  * cancel the first lock.
7692                                  * JRA - Do what Windows does (tm) :-).
7693                                  */
7694
7695 #if 0
7696                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7697                                 return NT_STATUS_DOS(ERRDOS,
7698                                                 ERRcancelviolation);
7699 #else
7700                                 /* Windows behavior. */
7701                                 if (i != 0) {
7702                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7703                                                 "cancel request\n"));
7704                                         continue;
7705                                 }
7706 #endif
7707                         }
7708
7709                         if (lp_blocking_locks(SNUM(conn))) {
7710
7711                                 /* Schedule a message to ourselves to
7712                                    remove the blocking lock record and
7713                                    return the right error. */
7714
7715                                 blr = blocking_lock_cancel_smb1(fsp,
7716                                                 e->smblctx,
7717                                                 e->offset,
7718                                                 e->count,
7719                                                 WINDOWS_LOCK,
7720                                                 type,
7721                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7722                                 if (blr == NULL) {
7723                                         return NT_STATUS_DOS(
7724                                                         ERRDOS,
7725                                                         ERRcancelviolation);
7726                                 }
7727                         }
7728                         /* Remove a matching pending lock. */
7729                         status = do_lock_cancel(fsp,
7730                                                 e->smblctx,
7731                                                 e->count,
7732                                                 e->offset,
7733                                                 WINDOWS_LOCK);
7734                 } else {
7735                         bool blocking_lock = timeout ? true : false;
7736                         bool defer_lock = false;
7737                         struct byte_range_lock *br_lck;
7738                         uint64_t block_smblctx;
7739
7740                         br_lck = do_lock(req->sconn->msg_ctx,
7741                                         fsp,
7742                                         e->smblctx,
7743                                         e->count,
7744                                         e->offset, 
7745                                         e->brltype,
7746                                         WINDOWS_LOCK,
7747                                         blocking_lock,
7748                                         &status,
7749                                         &block_smblctx);
7750
7751                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7752                                 /* Windows internal resolution for blocking locks seems
7753                                    to be about 200ms... Don't wait for less than that. JRA. */
7754                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7755                                         timeout = lp_lock_spin_time();
7756                                 }
7757                                 defer_lock = true;
7758                         }
7759
7760                         /* If a lock sent with timeout of zero would fail, and
7761                          * this lock has been requested multiple times,
7762                          * according to brl_lock_failed() we convert this
7763                          * request to a blocking lock with a timeout of between
7764                          * 150 - 300 milliseconds.
7765                          *
7766                          * If lp_lock_spin_time() has been set to 0, we skip
7767                          * this blocking retry and fail immediately.
7768                          *
7769                          * Replacement for do_lock_spin(). JRA. */
7770
7771                         if (!req->sconn->using_smb2 &&
7772                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7773                             lp_lock_spin_time() && !blocking_lock &&
7774                             NT_STATUS_EQUAL((status),
7775                                 NT_STATUS_FILE_LOCK_CONFLICT))
7776                         {
7777                                 defer_lock = true;
7778                                 timeout = lp_lock_spin_time();
7779                         }
7780
7781                         if (br_lck && defer_lock) {
7782                                 /*
7783                                  * A blocking lock was requested. Package up
7784                                  * this smb into a queued request and push it
7785                                  * onto the blocking lock queue.
7786                                  */
7787                                 if(push_blocking_lock_request(br_lck,
7788                                                         req,
7789                                                         fsp,
7790                                                         timeout,
7791                                                         i,
7792                                                         e->smblctx,
7793                                                         e->brltype,
7794                                                         WINDOWS_LOCK,
7795                                                         e->offset,
7796                                                         e->count,
7797                                                         block_smblctx)) {
7798                                         TALLOC_FREE(br_lck);
7799                                         *async = true;
7800                                         return NT_STATUS_OK;
7801                                 }
7802                         }
7803
7804                         TALLOC_FREE(br_lck);
7805                 }
7806
7807                 if (!NT_STATUS_IS_OK(status)) {
7808                         break;
7809                 }
7810         }
7811
7812         /* If any of the above locks failed, then we must unlock
7813            all of the previous locks (X/Open spec). */
7814
7815         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7816
7817                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7818                         i = -1; /* we want to skip the for loop */
7819                 }
7820
7821                 /*
7822                  * Ensure we don't do a remove on the lock that just failed,
7823                  * as under POSIX rules, if we have a lock already there, we
7824                  * will delete it (and we shouldn't) .....
7825                  */
7826                 for(i--; i >= 0; i--) {
7827                         struct smbd_lock_element *e = &locks[i];
7828
7829                         do_unlock(req->sconn->msg_ctx,
7830                                 fsp,
7831                                 e->smblctx,
7832                                 e->count,
7833                                 e->offset,
7834                                 WINDOWS_LOCK);
7835                 }
7836                 return status;
7837         }
7838
7839         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7840                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7841
7842         return NT_STATUS_OK;
7843 }
7844
7845 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7846                            files_struct *fsp,
7847                            uint16_t num_ulocks,
7848                            struct smbd_lock_element *ulocks)
7849 {
7850         int i;
7851
7852         for(i = 0; i < (int)num_ulocks; i++) {
7853                 struct smbd_lock_element *e = &ulocks[i];
7854                 NTSTATUS status;
7855
7856                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7857                           "pid %u, file %s\n", __func__,
7858                           (double)e->offset,
7859                           (double)e->count,
7860                           (unsigned int)e->smblctx,
7861                           fsp_str_dbg(fsp)));
7862
7863                 if (e->brltype != UNLOCK_LOCK) {
7864                         /* this can only happen with SMB2 */
7865                         return NT_STATUS_INVALID_PARAMETER;
7866                 }
7867
7868                 status = do_unlock(req->sconn->msg_ctx,
7869                                 fsp,
7870                                 e->smblctx,
7871                                 e->count,
7872                                 e->offset,
7873                                 WINDOWS_LOCK);
7874
7875                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7876                            nt_errstr(status)));
7877
7878                 if (!NT_STATUS_IS_OK(status)) {
7879                         return status;
7880                 }
7881         }
7882
7883         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7884                   num_ulocks));
7885
7886         return NT_STATUS_OK;
7887 }
7888
7889 /****************************************************************************
7890  Reply to a lockingX request.
7891 ****************************************************************************/
7892
7893 void reply_lockingX(struct smb_request *req)
7894 {
7895         connection_struct *conn = req->conn;
7896         files_struct *fsp;
7897         unsigned char locktype;
7898         unsigned char oplocklevel;
7899         uint16 num_ulocks;
7900         uint16 num_locks;
7901         int32 lock_timeout;
7902         int i;
7903         const uint8_t *data;
7904         bool large_file_format;
7905         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7906         struct smbd_lock_element *ulocks;
7907         struct smbd_lock_element *locks;
7908         bool async = false;
7909
7910         START_PROFILE(SMBlockingX);
7911
7912         if (req->wct < 8) {
7913                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7914                 END_PROFILE(SMBlockingX);
7915                 return;
7916         }
7917
7918         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7919         locktype = CVAL(req->vwv+3, 0);
7920         oplocklevel = CVAL(req->vwv+3, 1);
7921         num_ulocks = SVAL(req->vwv+6, 0);
7922         num_locks = SVAL(req->vwv+7, 0);
7923         lock_timeout = IVAL(req->vwv+4, 0);
7924         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7925
7926         if (!check_fsp(conn, req, fsp)) {
7927                 END_PROFILE(SMBlockingX);
7928                 return;
7929         }
7930
7931         data = req->buf;
7932
7933         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7934                 /* we don't support these - and CANCEL_LOCK makes w2k
7935                    and XP reboot so I don't really want to be
7936                    compatible! (tridge) */
7937                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7938                 END_PROFILE(SMBlockingX);
7939                 return;
7940         }
7941
7942         /* Check if this is an oplock break on a file
7943            we have granted an oplock on.
7944         */
7945         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7946                 /* Client can insist on breaking to none. */
7947                 bool break_to_none = (oplocklevel == 0);
7948                 bool result;
7949
7950                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7951                          "for %s\n", (unsigned int)oplocklevel,
7952                          fsp_fnum_dbg(fsp)));
7953
7954                 /*
7955                  * Make sure we have granted an exclusive or batch oplock on
7956                  * this file.
7957                  */
7958
7959                 if (fsp->oplock_type == 0) {
7960
7961                         /* The Samba4 nbench simulator doesn't understand
7962                            the difference between break to level2 and break
7963                            to none from level2 - it sends oplock break
7964                            replies in both cases. Don't keep logging an error
7965                            message here - just ignore it. JRA. */
7966
7967                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7968                                  "client for %s (oplock=%d) and no "
7969                                  "oplock granted on this file (%s).\n",
7970                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
7971                                  fsp_str_dbg(fsp)));
7972
7973                         /* if this is a pure oplock break request then don't
7974                          * send a reply */
7975                         if (num_locks == 0 && num_ulocks == 0) {
7976                                 END_PROFILE(SMBlockingX);
7977                                 return;
7978                         } else {
7979                                 END_PROFILE(SMBlockingX);
7980                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7981                                 return;
7982                         }
7983                 }
7984
7985                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7986                     (break_to_none)) {
7987                         result = remove_oplock(fsp);
7988                 } else {
7989                         result = downgrade_oplock(fsp);
7990                 }
7991
7992                 if (!result) {
7993                         DEBUG(0, ("reply_lockingX: error in removing "
7994                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7995                         /* Hmmm. Is this panic justified? */
7996                         smb_panic("internal tdb error");
7997                 }
7998
7999                 /* if this is a pure oplock break request then don't send a
8000                  * reply */
8001                 if (num_locks == 0 && num_ulocks == 0) {
8002                         /* Sanity check - ensure a pure oplock break is not a
8003                            chained request. */
8004                         if (CVAL(req->vwv+0, 0) != 0xff) {
8005                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8006                                          "break is a chained %d request !\n",
8007                                          (unsigned int)CVAL(req->vwv+0, 0)));
8008                         }
8009                         END_PROFILE(SMBlockingX);
8010                         return;
8011                 }
8012         }
8013
8014         if (req->buflen <
8015             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8016                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8017                 END_PROFILE(SMBlockingX);
8018                 return;
8019         }
8020
8021         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8022         if (ulocks == NULL) {
8023                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8024                 END_PROFILE(SMBlockingX);
8025                 return;
8026         }
8027
8028         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8029         if (locks == NULL) {
8030                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8031                 END_PROFILE(SMBlockingX);
8032                 return;
8033         }
8034
8035         /* Data now points at the beginning of the list
8036            of smb_unlkrng structs */
8037         for(i = 0; i < (int)num_ulocks; i++) {
8038                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8039                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8040                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8041                 ulocks[i].brltype = UNLOCK_LOCK;
8042         }
8043
8044         /* Now do any requested locks */
8045         data += ((large_file_format ? 20 : 10)*num_ulocks);
8046
8047         /* Data now points at the beginning of the list
8048            of smb_lkrng structs */
8049
8050         for(i = 0; i < (int)num_locks; i++) {
8051                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8052                 locks[i].count = get_lock_count(data, i, large_file_format);
8053                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8054
8055                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8056                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8057                                 locks[i].brltype = PENDING_READ_LOCK;
8058                         } else {
8059                                 locks[i].brltype = READ_LOCK;
8060                         }
8061                 } else {
8062                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8063                                 locks[i].brltype = PENDING_WRITE_LOCK;
8064                         } else {
8065                                 locks[i].brltype = WRITE_LOCK;
8066                         }
8067                 }
8068         }
8069
8070         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8071         if (!NT_STATUS_IS_OK(status)) {
8072                 END_PROFILE(SMBlockingX);
8073                 reply_nterror(req, status);
8074                 return;
8075         }
8076
8077         status = smbd_do_locking(req, fsp,
8078                                  locktype, lock_timeout,
8079                                  num_locks, locks,
8080                                  &async);
8081         if (!NT_STATUS_IS_OK(status)) {
8082                 END_PROFILE(SMBlockingX);
8083                 reply_nterror(req, status);
8084                 return;
8085         }
8086         if (async) {
8087                 END_PROFILE(SMBlockingX);
8088                 return;
8089         }
8090
8091         reply_outbuf(req, 2, 0);
8092         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8093         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8094
8095         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8096                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8097
8098         END_PROFILE(SMBlockingX);
8099 }
8100
8101 #undef DBGC_CLASS
8102 #define DBGC_CLASS DBGC_ALL
8103
8104 /****************************************************************************
8105  Reply to a SMBreadbmpx (read block multiplex) 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_readbmpx(struct smb_request *req)
8111 {
8112         START_PROFILE(SMBreadBmpx);
8113         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8114         END_PROFILE(SMBreadBmpx);
8115         return;
8116 }
8117
8118 /****************************************************************************
8119  Reply to a SMBreadbs (read block multiplex secondary) request.
8120  Always reply with an error, if someone has a platform really needs this,
8121  please contact vl@samba.org
8122 ****************************************************************************/
8123
8124 void reply_readbs(struct smb_request *req)
8125 {
8126         START_PROFILE(SMBreadBs);
8127         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8128         END_PROFILE(SMBreadBs);
8129         return;
8130 }
8131
8132 /****************************************************************************
8133  Reply to a SMBsetattrE.
8134 ****************************************************************************/
8135
8136 void reply_setattrE(struct smb_request *req)
8137 {
8138         connection_struct *conn = req->conn;
8139         struct smb_file_time ft;
8140         files_struct *fsp;
8141         NTSTATUS status;
8142
8143         START_PROFILE(SMBsetattrE);
8144         ZERO_STRUCT(ft);
8145
8146         if (req->wct < 7) {
8147                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8148                 goto out;
8149         }
8150
8151         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8152
8153         if(!fsp || (fsp->conn != conn)) {
8154                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8155                 goto out;
8156         }
8157
8158         /*
8159          * Convert the DOS times into unix times.
8160          */
8161
8162         ft.atime = convert_time_t_to_timespec(
8163             srv_make_unix_date2(req->vwv+3));
8164         ft.mtime = convert_time_t_to_timespec(
8165             srv_make_unix_date2(req->vwv+5));
8166         ft.create_time = convert_time_t_to_timespec(
8167             srv_make_unix_date2(req->vwv+1));
8168
8169         reply_outbuf(req, 0, 0);
8170
8171         /* 
8172          * Patch from Ray Frush <frush@engr.colostate.edu>
8173          * Sometimes times are sent as zero - ignore them.
8174          */
8175
8176         /* Ensure we have a valid stat struct for the source. */
8177         status = vfs_stat_fsp(fsp);
8178         if (!NT_STATUS_IS_OK(status)) {
8179                 reply_nterror(req, status);
8180                 goto out;
8181         }
8182
8183         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8184                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8185                 goto out;
8186         }
8187
8188         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8189         if (!NT_STATUS_IS_OK(status)) {
8190                 reply_nterror(req, status);
8191                 goto out;
8192         }
8193
8194         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8195                " createtime=%u\n",
8196                 fsp_fnum_dbg(fsp),
8197                 (unsigned int)ft.atime.tv_sec,
8198                 (unsigned int)ft.mtime.tv_sec,
8199                 (unsigned int)ft.create_time.tv_sec
8200                 ));
8201  out:
8202         END_PROFILE(SMBsetattrE);
8203         return;
8204 }
8205
8206
8207 /* Back from the dead for OS/2..... JRA. */
8208
8209 /****************************************************************************
8210  Reply to a SMBwritebmpx (write block multiplex primary) 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_writebmpx(struct smb_request *req)
8216 {
8217         START_PROFILE(SMBwriteBmpx);
8218         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8219         END_PROFILE(SMBwriteBmpx);
8220         return;
8221 }
8222
8223 /****************************************************************************
8224  Reply to a SMBwritebs (write block multiplex secondary) request.
8225  Always reply with an error, if someone has a platform really needs this,
8226  please contact vl@samba.org
8227 ****************************************************************************/
8228
8229 void reply_writebs(struct smb_request *req)
8230 {
8231         START_PROFILE(SMBwriteBs);
8232         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8233         END_PROFILE(SMBwriteBs);
8234         return;
8235 }
8236
8237 /****************************************************************************
8238  Reply to a SMBgetattrE.
8239 ****************************************************************************/
8240
8241 void reply_getattrE(struct smb_request *req)
8242 {
8243         connection_struct *conn = req->conn;
8244         int mode;
8245         files_struct *fsp;
8246         struct timespec create_ts;
8247
8248         START_PROFILE(SMBgetattrE);
8249
8250         if (req->wct < 1) {
8251                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8252                 END_PROFILE(SMBgetattrE);
8253                 return;
8254         }
8255
8256         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8257
8258         if(!fsp || (fsp->conn != conn)) {
8259                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8260                 END_PROFILE(SMBgetattrE);
8261                 return;
8262         }
8263
8264         /* Do an fstat on this file */
8265         if(fsp_stat(fsp)) {
8266                 reply_nterror(req, map_nt_error_from_unix(errno));
8267                 END_PROFILE(SMBgetattrE);
8268                 return;
8269         }
8270
8271         mode = dos_mode(conn, fsp->fsp_name);
8272
8273         /*
8274          * Convert the times into dos times. Set create
8275          * date to be last modify date as UNIX doesn't save
8276          * this.
8277          */
8278
8279         reply_outbuf(req, 11, 0);
8280
8281         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8282         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8283         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8284                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8285         /* Should we check pending modtime here ? JRA */
8286         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8287                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8288
8289         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8290                 SIVAL(req->outbuf, smb_vwv6, 0);
8291                 SIVAL(req->outbuf, smb_vwv8, 0);
8292         } else {
8293                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8294                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8295                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8296         }
8297         SSVAL(req->outbuf,smb_vwv10, mode);
8298
8299         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8300
8301         END_PROFILE(SMBgetattrE);
8302         return;
8303 }