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