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