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