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