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