fix 'Invalid read of size 1' in reply_search
[bbaumbach/samba-autobuild/.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #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 missmatch. */
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 (file_find_subpath(fsp)) {
2680                         return NT_STATUS_ACCESS_DENIED;
2681                 }
2682                 return NT_STATUS_OK;
2683         }
2684
2685         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2686                 return NT_STATUS_OK;
2687         }
2688
2689         return NT_STATUS_ACCESS_DENIED;
2690 }
2691
2692 /*******************************************************************
2693  * unlink a file with all relevant access checks
2694  *******************************************************************/
2695
2696 static NTSTATUS do_unlink(connection_struct *conn,
2697                         struct smb_request *req,
2698                         struct smb_filename *smb_fname,
2699                         uint32_t dirtype)
2700 {
2701         uint32_t fattr;
2702         files_struct *fsp;
2703         uint32_t dirtype_orig = dirtype;
2704         NTSTATUS status;
2705         int ret;
2706         bool posix_paths = lp_posix_pathnames();
2707
2708         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2709                   smb_fname_str_dbg(smb_fname),
2710                   dirtype));
2711
2712         if (!CAN_WRITE(conn)) {
2713                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2714         }
2715
2716         if (posix_paths) {
2717                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2718         } else {
2719                 ret = SMB_VFS_STAT(conn, smb_fname);
2720         }
2721         if (ret != 0) {
2722                 return map_nt_error_from_unix(errno);
2723         }
2724
2725         fattr = dos_mode(conn, smb_fname);
2726
2727         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2728                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2729         }
2730
2731         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2732         if (!dirtype) {
2733                 return NT_STATUS_NO_SUCH_FILE;
2734         }
2735
2736         if (!dir_check_ftype(fattr, dirtype)) {
2737                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2738                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2739                 }
2740                 return NT_STATUS_NO_SUCH_FILE;
2741         }
2742
2743         if (dirtype_orig & 0x8000) {
2744                 /* These will never be set for POSIX. */
2745                 return NT_STATUS_NO_SUCH_FILE;
2746         }
2747
2748 #if 0
2749         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2750                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2751         }
2752
2753         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2754                 return NT_STATUS_NO_SUCH_FILE;
2755         }
2756
2757         if (dirtype & 0xFF00) {
2758                 /* These will never be set for POSIX. */
2759                 return NT_STATUS_NO_SUCH_FILE;
2760         }
2761
2762         dirtype &= 0xFF;
2763         if (!dirtype) {
2764                 return NT_STATUS_NO_SUCH_FILE;
2765         }
2766
2767         /* Can't delete a directory. */
2768         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2769                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2770         }
2771 #endif
2772
2773 #if 0 /* JRATEST */
2774         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2775                 return NT_STATUS_OBJECT_NAME_INVALID;
2776 #endif /* JRATEST */
2777
2778         /* On open checks the open itself will check the share mode, so
2779            don't do it here as we'll get it wrong. */
2780
2781         status = SMB_VFS_CREATE_FILE
2782                 (conn,                  /* conn */
2783                  req,                   /* req */
2784                  0,                     /* root_dir_fid */
2785                  smb_fname,             /* fname */
2786                  DELETE_ACCESS,         /* access_mask */
2787                  FILE_SHARE_NONE,       /* share_access */
2788                  FILE_OPEN,             /* create_disposition*/
2789                  FILE_NON_DIRECTORY_FILE, /* create_options */
2790                                         /* file_attributes */
2791                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2792                                 FILE_ATTRIBUTE_NORMAL,
2793                  0,                     /* oplock_request */
2794                  NULL,                  /* lease */
2795                  0,                     /* allocation_size */
2796                  0,                     /* private_flags */
2797                  NULL,                  /* sd */
2798                  NULL,                  /* ea_list */
2799                  &fsp,                  /* result */
2800                  NULL,                  /* pinfo */
2801                  NULL, NULL);           /* create context */
2802
2803         if (!NT_STATUS_IS_OK(status)) {
2804                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2805                            nt_errstr(status)));
2806                 return status;
2807         }
2808
2809         status = can_set_delete_on_close(fsp, fattr);
2810         if (!NT_STATUS_IS_OK(status)) {
2811                 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2812                         "(%s)\n",
2813                         smb_fname_str_dbg(smb_fname),
2814                         nt_errstr(status)));
2815                 close_file(req, fsp, NORMAL_CLOSE);
2816                 return status;
2817         }
2818
2819         /* The set is across all open files on this dev/inode pair. */
2820         if (!set_delete_on_close(fsp, True,
2821                                 conn->session_info->security_token,
2822                                 conn->session_info->unix_token)) {
2823                 close_file(req, fsp, NORMAL_CLOSE);
2824                 return NT_STATUS_ACCESS_DENIED;
2825         }
2826
2827         return close_file(req, fsp, NORMAL_CLOSE);
2828 }
2829
2830 /****************************************************************************
2831  The guts of the unlink command, split out so it may be called by the NT SMB
2832  code.
2833 ****************************************************************************/
2834
2835 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2836                           uint32_t dirtype, struct smb_filename *smb_fname,
2837                           bool has_wild)
2838 {
2839         char *fname_dir = NULL;
2840         char *fname_mask = NULL;
2841         int count=0;
2842         NTSTATUS status = NT_STATUS_OK;
2843         TALLOC_CTX *ctx = talloc_tos();
2844
2845         /* Split up the directory from the filename/mask. */
2846         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2847                                       &fname_dir, &fname_mask);
2848         if (!NT_STATUS_IS_OK(status)) {
2849                 goto out;
2850         }
2851
2852         /*
2853          * We should only check the mangled cache
2854          * here if unix_convert failed. This means
2855          * that the path in 'mask' doesn't exist
2856          * on the file system and so we need to look
2857          * for a possible mangle. This patch from
2858          * Tine Smukavec <valentin.smukavec@hermes.si>.
2859          */
2860
2861         if (!VALID_STAT(smb_fname->st) &&
2862             mangle_is_mangled(fname_mask, conn->params)) {
2863                 char *new_mask = NULL;
2864                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2865                                             &new_mask, conn->params);
2866                 if (new_mask) {
2867                         TALLOC_FREE(fname_mask);
2868                         fname_mask = new_mask;
2869                 }
2870         }
2871
2872         if (!has_wild) {
2873
2874                 /*
2875                  * Only one file needs to be unlinked. Append the mask back
2876                  * onto the directory.
2877                  */
2878                 TALLOC_FREE(smb_fname->base_name);
2879                 if (ISDOT(fname_dir)) {
2880                         /* Ensure we use canonical names on open. */
2881                         smb_fname->base_name = talloc_asprintf(smb_fname,
2882                                                         "%s",
2883                                                         fname_mask);
2884                 } else {
2885                         smb_fname->base_name = talloc_asprintf(smb_fname,
2886                                                         "%s/%s",
2887                                                         fname_dir,
2888                                                         fname_mask);
2889                 }
2890                 if (!smb_fname->base_name) {
2891                         status = NT_STATUS_NO_MEMORY;
2892                         goto out;
2893                 }
2894                 if (dirtype == 0) {
2895                         dirtype = FILE_ATTRIBUTE_NORMAL;
2896                 }
2897
2898                 status = check_name(conn, smb_fname->base_name);
2899                 if (!NT_STATUS_IS_OK(status)) {
2900                         goto out;
2901                 }
2902
2903                 status = do_unlink(conn, req, smb_fname, dirtype);
2904                 if (!NT_STATUS_IS_OK(status)) {
2905                         goto out;
2906                 }
2907
2908                 count++;
2909         } else {
2910                 struct smb_Dir *dir_hnd = NULL;
2911                 long offset = 0;
2912                 const char *dname = NULL;
2913                 char *talloced = NULL;
2914
2915                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2916                         status = NT_STATUS_OBJECT_NAME_INVALID;
2917                         goto out;
2918                 }
2919                 if (dirtype == 0) {
2920                         dirtype = FILE_ATTRIBUTE_NORMAL;
2921                 }
2922
2923                 if (strequal(fname_mask,"????????.???")) {
2924                         TALLOC_FREE(fname_mask);
2925                         fname_mask = talloc_strdup(ctx, "*");
2926                         if (!fname_mask) {
2927                                 status = NT_STATUS_NO_MEMORY;
2928                                 goto out;
2929                         }
2930                 }
2931
2932                 status = check_name(conn, fname_dir);
2933                 if (!NT_STATUS_IS_OK(status)) {
2934                         goto out;
2935                 }
2936
2937                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2938                                   dirtype);
2939                 if (dir_hnd == NULL) {
2940                         status = map_nt_error_from_unix(errno);
2941                         goto out;
2942                 }
2943
2944                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2945                    the pattern matches against the long name, otherwise the short name 
2946                    We don't implement this yet XXXX
2947                 */
2948
2949                 status = NT_STATUS_NO_SUCH_FILE;
2950
2951                 while ((dname = ReadDirName(dir_hnd, &offset,
2952                                             &smb_fname->st, &talloced))) {
2953                         TALLOC_CTX *frame = talloc_stackframe();
2954
2955                         if (!is_visible_file(conn, fname_dir, dname,
2956                                              &smb_fname->st, true)) {
2957                                 TALLOC_FREE(frame);
2958                                 TALLOC_FREE(talloced);
2959                                 continue;
2960                         }
2961
2962                         /* Quick check for "." and ".." */
2963                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2964                                 TALLOC_FREE(frame);
2965                                 TALLOC_FREE(talloced);
2966                                 continue;
2967                         }
2968
2969                         if(!mask_match(dname, fname_mask,
2970                                        conn->case_sensitive)) {
2971                                 TALLOC_FREE(frame);
2972                                 TALLOC_FREE(talloced);
2973                                 continue;
2974                         }
2975
2976                         TALLOC_FREE(smb_fname->base_name);
2977                         if (ISDOT(fname_dir)) {
2978                                 /* Ensure we use canonical names on open. */
2979                                 smb_fname->base_name =
2980                                         talloc_asprintf(smb_fname, "%s",
2981                                                 dname);
2982                         } else {
2983                                 smb_fname->base_name =
2984                                         talloc_asprintf(smb_fname, "%s/%s",
2985                                                 fname_dir, dname);
2986                         }
2987
2988                         if (!smb_fname->base_name) {
2989                                 TALLOC_FREE(dir_hnd);
2990                                 status = NT_STATUS_NO_MEMORY;
2991                                 TALLOC_FREE(frame);
2992                                 TALLOC_FREE(talloced);
2993                                 goto out;
2994                         }
2995
2996                         status = check_name(conn, smb_fname->base_name);
2997                         if (!NT_STATUS_IS_OK(status)) {
2998                                 TALLOC_FREE(dir_hnd);
2999                                 TALLOC_FREE(frame);
3000                                 TALLOC_FREE(talloced);
3001                                 goto out;
3002                         }
3003
3004                         status = do_unlink(conn, req, smb_fname, dirtype);
3005                         if (!NT_STATUS_IS_OK(status)) {
3006                                 TALLOC_FREE(dir_hnd);
3007                                 TALLOC_FREE(frame);
3008                                 TALLOC_FREE(talloced);
3009                                 goto out;
3010                         }
3011
3012                         count++;
3013                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3014                                  smb_fname->base_name));
3015
3016                         TALLOC_FREE(frame);
3017                         TALLOC_FREE(talloced);
3018                 }
3019                 TALLOC_FREE(dir_hnd);
3020         }
3021
3022         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3023                 status = map_nt_error_from_unix(errno);
3024         }
3025
3026  out:
3027         TALLOC_FREE(fname_dir);
3028         TALLOC_FREE(fname_mask);
3029         return status;
3030 }
3031
3032 /****************************************************************************
3033  Reply to a unlink
3034 ****************************************************************************/
3035
3036 void reply_unlink(struct smb_request *req)
3037 {
3038         connection_struct *conn = req->conn;
3039         char *name = NULL;
3040         struct smb_filename *smb_fname = NULL;
3041         uint32_t dirtype;
3042         NTSTATUS status;
3043         bool path_contains_wcard = False;
3044         TALLOC_CTX *ctx = talloc_tos();
3045
3046         START_PROFILE(SMBunlink);
3047
3048         if (req->wct < 1) {
3049                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3050                 goto out;
3051         }
3052
3053         dirtype = SVAL(req->vwv+0, 0);
3054
3055         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3056                                   STR_TERMINATE, &status,
3057                                   &path_contains_wcard);
3058         if (!NT_STATUS_IS_OK(status)) {
3059                 reply_nterror(req, status);
3060                 goto out;
3061         }
3062
3063         status = filename_convert(ctx, conn,
3064                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
3065                                   name,
3066                                   UCF_COND_ALLOW_WCARD_LCOMP,
3067                                   &path_contains_wcard,
3068                                   &smb_fname);
3069         if (!NT_STATUS_IS_OK(status)) {
3070                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3071                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3072                                         ERRSRV, ERRbadpath);
3073                         goto out;
3074                 }
3075                 reply_nterror(req, status);
3076                 goto out;
3077         }
3078
3079         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3080
3081         status = unlink_internals(conn, req, dirtype, smb_fname,
3082                                   path_contains_wcard);
3083         if (!NT_STATUS_IS_OK(status)) {
3084                 if (open_was_deferred(req->xconn, req->mid)) {
3085                         /* We have re-scheduled this call. */
3086                         goto out;
3087                 }
3088                 reply_nterror(req, status);
3089                 goto out;
3090         }
3091
3092         reply_outbuf(req, 0, 0);
3093  out:
3094         TALLOC_FREE(smb_fname);
3095         END_PROFILE(SMBunlink);
3096         return;
3097 }
3098
3099 /****************************************************************************
3100  Fail for readbraw.
3101 ****************************************************************************/
3102
3103 static void fail_readraw(void)
3104 {
3105         const char *errstr = talloc_asprintf(talloc_tos(),
3106                         "FAIL ! reply_readbraw: socket write fail (%s)",
3107                         strerror(errno));
3108         if (!errstr) {
3109                 errstr = "";
3110         }
3111         exit_server_cleanly(errstr);
3112 }
3113
3114 /****************************************************************************
3115  Fake (read/write) sendfile. Returns -1 on read or write fail.
3116 ****************************************************************************/
3117
3118 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3119                       off_t startpos, size_t nread)
3120 {
3121         size_t bufsize;
3122         size_t tosend = nread;
3123         char *buf;
3124
3125         if (nread == 0) {
3126                 return 0;
3127         }
3128
3129         bufsize = MIN(nread, 65536);
3130
3131         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3132                 return -1;
3133         }
3134
3135         while (tosend > 0) {
3136                 ssize_t ret;
3137                 size_t cur_read;
3138
3139                 cur_read = MIN(tosend, bufsize);
3140                 ret = read_file(fsp,buf,startpos,cur_read);
3141                 if (ret == -1) {
3142                         SAFE_FREE(buf);
3143                         return -1;
3144                 }
3145
3146                 /* If we had a short read, fill with zeros. */
3147                 if (ret < cur_read) {
3148                         memset(buf + ret, '\0', cur_read - ret);
3149                 }
3150
3151                 ret = write_data(xconn->transport.sock, buf, cur_read);
3152                 if (ret != cur_read) {
3153                         int saved_errno = errno;
3154                         /*
3155                          * Try and give an error message saying what
3156                          * client failed.
3157                          */
3158                         DEBUG(0, ("write_data failed for client %s. "
3159                                   "Error %s\n",
3160                                   smbXsrv_connection_dbg(xconn),
3161                                   strerror(saved_errno)));
3162                         SAFE_FREE(buf);
3163                         errno = saved_errno;
3164                         return -1;
3165                 }
3166                 tosend -= cur_read;
3167                 startpos += cur_read;
3168         }
3169
3170         SAFE_FREE(buf);
3171         return (ssize_t)nread;
3172 }
3173
3174 /****************************************************************************
3175  Deal with the case of sendfile reading less bytes from the file than
3176  requested. Fill with zeros (all we can do). Returns 0 on success
3177 ****************************************************************************/
3178
3179 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3180                             files_struct *fsp,
3181                             ssize_t nread,
3182                             size_t headersize,
3183                             size_t smb_maxcnt)
3184 {
3185 #define SHORT_SEND_BUFSIZE 1024
3186         if (nread < headersize) {
3187                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3188                         "header for file %s (%s). Terminating\n",
3189                         fsp_str_dbg(fsp), strerror(errno)));
3190                 return -1;
3191         }
3192
3193         nread -= headersize;
3194
3195         if (nread < smb_maxcnt) {
3196                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3197                 if (!buf) {
3198                         DEBUG(0,("sendfile_short_send: malloc failed "
3199                                 "for file %s (%s). Terminating\n",
3200                                 fsp_str_dbg(fsp), strerror(errno)));
3201                         return -1;
3202                 }
3203
3204                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3205                         "with zeros !\n", fsp_str_dbg(fsp)));
3206
3207                 while (nread < smb_maxcnt) {
3208                         /*
3209                          * We asked for the real file size and told sendfile
3210                          * to not go beyond the end of the file. But it can
3211                          * happen that in between our fstat call and the
3212                          * sendfile call the file was truncated. This is very
3213                          * bad because we have already announced the larger
3214                          * number of bytes to the client.
3215                          *
3216                          * The best we can do now is to send 0-bytes, just as
3217                          * a read from a hole in a sparse file would do.
3218                          *
3219                          * This should happen rarely enough that I don't care
3220                          * about efficiency here :-)
3221                          */
3222                         size_t to_write;
3223                         ssize_t ret;
3224
3225                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3226                         ret = write_data(xconn->transport.sock, buf, to_write);
3227                         if (ret != to_write) {
3228                                 int saved_errno = errno;
3229                                 /*
3230                                  * Try and give an error message saying what
3231                                  * client failed.
3232                                  */
3233                                 DEBUG(0, ("write_data failed for client %s. "
3234                                           "Error %s\n",
3235                                           smbXsrv_connection_dbg(xconn),
3236                                           strerror(saved_errno)));
3237                                 errno = saved_errno;
3238                                 return -1;
3239                         }
3240                         nread += to_write;
3241                 }
3242                 SAFE_FREE(buf);
3243         }
3244
3245         return 0;
3246 }
3247
3248 /****************************************************************************
3249  Return a readbraw error (4 bytes of zero).
3250 ****************************************************************************/
3251
3252 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3253 {
3254         char header[4];
3255
3256         SIVAL(header,0,0);
3257
3258         smbd_lock_socket(xconn);
3259         if (write_data(xconn->transport.sock,header,4) != 4) {
3260                 int saved_errno = errno;
3261                 /*
3262                  * Try and give an error message saying what
3263                  * client failed.
3264                  */
3265                 DEBUG(0, ("write_data failed for client %s. "
3266                           "Error %s\n",
3267                           smbXsrv_connection_dbg(xconn),
3268                           strerror(saved_errno)));
3269                 errno = saved_errno;
3270
3271                 fail_readraw();
3272         }
3273         smbd_unlock_socket(xconn);
3274 }
3275
3276 /****************************************************************************
3277  Use sendfile in readbraw.
3278 ****************************************************************************/
3279
3280 static void send_file_readbraw(connection_struct *conn,
3281                                struct smb_request *req,
3282                                files_struct *fsp,
3283                                off_t startpos,
3284                                size_t nread,
3285                                ssize_t mincount)
3286 {
3287         struct smbXsrv_connection *xconn = req->xconn;
3288         char *outbuf = NULL;
3289         ssize_t ret=0;
3290
3291         /*
3292          * We can only use sendfile on a non-chained packet 
3293          * but we can use on a non-oplocked file. tridge proved this
3294          * on a train in Germany :-). JRA.
3295          * reply_readbraw has already checked the length.
3296          */
3297
3298         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3299             (fsp->wcp == NULL) &&
3300             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3301                 ssize_t sendfile_read = -1;
3302                 char header[4];
3303                 DATA_BLOB header_blob;
3304
3305                 _smb_setlen(header,nread);
3306                 header_blob = data_blob_const(header, 4);
3307
3308                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3309                                                  &header_blob, startpos,
3310                                                  nread);
3311                 if (sendfile_read == -1) {
3312                         /* Returning ENOSYS means no data at all was sent.
3313                          * Do this as a normal read. */
3314                         if (errno == ENOSYS) {
3315                                 goto normal_readbraw;
3316                         }
3317
3318                         /*
3319                          * Special hack for broken Linux with no working sendfile. If we
3320                          * return EINTR we sent the header but not the rest of the data.
3321                          * Fake this up by doing read/write calls.
3322                          */
3323                         if (errno == EINTR) {
3324                                 /* Ensure we don't do this again. */
3325                                 set_use_sendfile(SNUM(conn), False);
3326                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3327
3328                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3329                                         DEBUG(0,("send_file_readbraw: "
3330                                                  "fake_sendfile failed for "
3331                                                  "file %s (%s).\n",
3332                                                  fsp_str_dbg(fsp),
3333                                                  strerror(errno)));
3334                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3335                                 }
3336                                 return;
3337                         }
3338
3339                         DEBUG(0,("send_file_readbraw: sendfile failed for "
3340                                  "file %s (%s). Terminating\n",
3341                                  fsp_str_dbg(fsp), strerror(errno)));
3342                         exit_server_cleanly("send_file_readbraw sendfile failed");
3343                 } else if (sendfile_read == 0) {
3344                         /*
3345                          * Some sendfile implementations return 0 to indicate
3346                          * that there was a short read, but nothing was
3347                          * actually written to the socket.  In this case,
3348                          * fallback to the normal read path so the header gets
3349                          * the correct byte count.
3350                          */
3351                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3352                                   "bytes falling back to the normal read: "
3353                                   "%s\n", fsp_str_dbg(fsp)));
3354                         goto normal_readbraw;
3355                 }
3356
3357                 /* Deal with possible short send. */
3358                 if (sendfile_read != 4+nread) {
3359                         ret = sendfile_short_send(xconn, fsp,
3360                                                   sendfile_read, 4, nread);
3361                         if (ret == -1) {
3362                                 fail_readraw();
3363                         }
3364                 }
3365                 return;
3366         }
3367
3368 normal_readbraw:
3369
3370         outbuf = talloc_array(NULL, char, nread+4);
3371         if (!outbuf) {
3372                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3373                         (unsigned)(nread+4)));
3374                 reply_readbraw_error(xconn);
3375                 return;
3376         }
3377
3378         if (nread > 0) {
3379                 ret = read_file(fsp,outbuf+4,startpos,nread);
3380 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3381                 if (ret < mincount)
3382                         ret = 0;
3383 #else
3384                 if (ret < nread)
3385                         ret = 0;
3386 #endif
3387         }
3388
3389         _smb_setlen(outbuf,ret);
3390         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3391                 int saved_errno = errno;
3392                 /*
3393                  * Try and give an error message saying what
3394                  * client failed.
3395                  */
3396                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3397                           smbXsrv_connection_dbg(xconn),
3398                           strerror(saved_errno)));
3399                 errno = saved_errno;
3400
3401                 fail_readraw();
3402         }
3403
3404         TALLOC_FREE(outbuf);
3405 }
3406
3407 /****************************************************************************
3408  Reply to a readbraw (core+ protocol).
3409 ****************************************************************************/
3410
3411 void reply_readbraw(struct smb_request *req)
3412 {
3413         connection_struct *conn = req->conn;
3414         struct smbXsrv_connection *xconn = req->xconn;
3415         ssize_t maxcount,mincount;
3416         size_t nread = 0;
3417         off_t startpos;
3418         files_struct *fsp;
3419         struct lock_struct lock;
3420         off_t size = 0;
3421
3422         START_PROFILE(SMBreadbraw);
3423
3424         if (srv_is_signing_active(xconn) || req->encrypted) {
3425                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3426                         "raw reads/writes are disallowed.");
3427         }
3428
3429         if (req->wct < 8) {
3430                 reply_readbraw_error(xconn);
3431                 END_PROFILE(SMBreadbraw);
3432                 return;
3433         }
3434
3435         if (xconn->smb1.echo_handler.trusted_fde) {
3436                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3437                          "'async smb echo handler = yes'\n"));
3438                 reply_readbraw_error(xconn);
3439                 END_PROFILE(SMBreadbraw);
3440                 return;
3441         }
3442
3443         /*
3444          * Special check if an oplock break has been issued
3445          * and the readraw request croses on the wire, we must
3446          * return a zero length response here.
3447          */
3448
3449         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3450
3451         /*
3452          * We have to do a check_fsp by hand here, as
3453          * we must always return 4 zero bytes on error,
3454          * not a NTSTATUS.
3455          */
3456
3457         if (!fsp || !conn || conn != fsp->conn ||
3458                         req->vuid != fsp->vuid ||
3459                         fsp->is_directory || fsp->fh->fd == -1) {
3460                 /*
3461                  * fsp could be NULL here so use the value from the packet. JRA.
3462                  */
3463                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3464                         "- cache prime?\n",
3465                         (int)SVAL(req->vwv+0, 0)));
3466                 reply_readbraw_error(xconn);
3467                 END_PROFILE(SMBreadbraw);
3468                 return;
3469         }
3470
3471         /* Do a "by hand" version of CHECK_READ. */
3472         if (!(fsp->can_read ||
3473                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3474                                 (fsp->access_mask & FILE_EXECUTE)))) {
3475                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3476                                 (int)SVAL(req->vwv+0, 0)));
3477                 reply_readbraw_error(xconn);
3478                 END_PROFILE(SMBreadbraw);
3479                 return;
3480         }
3481
3482         flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3483
3484         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3485         if(req->wct == 10) {
3486                 /*
3487                  * This is a large offset (64 bit) read.
3488                  */
3489
3490                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3491
3492                 if(startpos < 0) {
3493                         DEBUG(0,("reply_readbraw: negative 64 bit "
3494                                 "readraw offset (%.0f) !\n",
3495                                 (double)startpos ));
3496                         reply_readbraw_error(xconn);
3497                         END_PROFILE(SMBreadbraw);
3498                         return;
3499                 }
3500         }
3501
3502         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3503         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3504
3505         /* ensure we don't overrun the packet size */
3506         maxcount = MIN(65535,maxcount);
3507
3508         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3509             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3510             &lock);
3511
3512         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3513                 reply_readbraw_error(xconn);
3514                 END_PROFILE(SMBreadbraw);
3515                 return;
3516         }
3517
3518         if (fsp_stat(fsp) == 0) {
3519                 size = fsp->fsp_name->st.st_ex_size;
3520         }
3521
3522         if (startpos >= size) {
3523                 nread = 0;
3524         } else {
3525                 nread = MIN(maxcount,(size - startpos));
3526         }
3527
3528 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3529         if (nread < mincount)
3530                 nread = 0;
3531 #endif
3532
3533         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3534                 "min=%lu nread=%lu\n",
3535                 fsp_fnum_dbg(fsp), (double)startpos,
3536                 (unsigned long)maxcount,
3537                 (unsigned long)mincount,
3538                 (unsigned long)nread ) );
3539
3540         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3541
3542         DEBUG(5,("reply_readbraw finished\n"));
3543
3544         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3545
3546         END_PROFILE(SMBreadbraw);
3547         return;
3548 }
3549
3550 #undef DBGC_CLASS
3551 #define DBGC_CLASS DBGC_LOCKING
3552
3553 /****************************************************************************
3554  Reply to a lockread (core+ protocol).
3555 ****************************************************************************/
3556
3557 void reply_lockread(struct smb_request *req)
3558 {
3559         connection_struct *conn = req->conn;
3560         ssize_t nread = -1;
3561         char *data;
3562         off_t startpos;
3563         size_t numtoread;
3564         size_t maxtoread;
3565         NTSTATUS status;
3566         files_struct *fsp;
3567         struct byte_range_lock *br_lck = NULL;
3568         char *p = NULL;
3569         struct smbXsrv_connection *xconn = req->xconn;
3570
3571         START_PROFILE(SMBlockread);
3572
3573         if (req->wct < 5) {
3574                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3575                 END_PROFILE(SMBlockread);
3576                 return;
3577         }
3578
3579         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3580
3581         if (!check_fsp(conn, req, fsp)) {
3582                 END_PROFILE(SMBlockread);
3583                 return;
3584         }
3585
3586         if (!CHECK_READ(fsp,req)) {
3587                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3588                 END_PROFILE(SMBlockread);
3589                 return;
3590         }
3591
3592         numtoread = SVAL(req->vwv+1, 0);
3593         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3594
3595         /*
3596          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3597          * protocol request that predates the read/write lock concept. 
3598          * Thus instead of asking for a read lock here we need to ask
3599          * for a write lock. JRA.
3600          * Note that the requested lock size is unaffected by max_send.
3601          */
3602
3603         br_lck = do_lock(req->sconn->msg_ctx,
3604                         fsp,
3605                         (uint64_t)req->smbpid,
3606                         (uint64_t)numtoread,
3607                         (uint64_t)startpos,
3608                         WRITE_LOCK,
3609                         WINDOWS_LOCK,
3610                         False, /* Non-blocking lock. */
3611                         &status,
3612                         NULL);
3613         TALLOC_FREE(br_lck);
3614
3615         if (NT_STATUS_V(status)) {
3616                 reply_nterror(req, status);
3617                 END_PROFILE(SMBlockread);
3618                 return;
3619         }
3620
3621         /*
3622          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3623          */
3624         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3625
3626         if (numtoread > maxtoread) {
3627                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3628 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3629                         (unsigned int)numtoread, (unsigned int)maxtoread,
3630                         (unsigned int)xconn->smb1.sessions.max_send));
3631                 numtoread = maxtoread;
3632         }
3633
3634         reply_outbuf(req, 5, numtoread + 3);
3635
3636         data = smb_buf(req->outbuf) + 3;
3637
3638         nread = read_file(fsp,data,startpos,numtoread);
3639
3640         if (nread < 0) {
3641                 reply_nterror(req, map_nt_error_from_unix(errno));
3642                 END_PROFILE(SMBlockread);
3643                 return;
3644         }
3645
3646         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3647
3648         SSVAL(req->outbuf,smb_vwv0,nread);
3649         SSVAL(req->outbuf,smb_vwv5,nread+3);
3650         p = smb_buf(req->outbuf);
3651         SCVAL(p,0,0); /* pad byte. */
3652         SSVAL(p,1,nread);
3653
3654         DEBUG(3,("lockread %s num=%d nread=%d\n",
3655                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3656
3657         END_PROFILE(SMBlockread);
3658         return;
3659 }
3660
3661 #undef DBGC_CLASS
3662 #define DBGC_CLASS DBGC_ALL
3663
3664 /****************************************************************************
3665  Reply to a read.
3666 ****************************************************************************/
3667
3668 void reply_read(struct smb_request *req)
3669 {
3670         connection_struct *conn = req->conn;
3671         size_t numtoread;
3672         size_t maxtoread;
3673         ssize_t nread = 0;
3674         char *data;
3675         off_t startpos;
3676         files_struct *fsp;
3677         struct lock_struct lock;
3678         struct smbXsrv_connection *xconn = req->xconn;
3679
3680         START_PROFILE(SMBread);
3681
3682         if (req->wct < 3) {
3683                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3684                 END_PROFILE(SMBread);
3685                 return;
3686         }
3687
3688         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3689
3690         if (!check_fsp(conn, req, fsp)) {
3691                 END_PROFILE(SMBread);
3692                 return;
3693         }
3694
3695         if (!CHECK_READ(fsp,req)) {
3696                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3697                 END_PROFILE(SMBread);
3698                 return;
3699         }
3700
3701         numtoread = SVAL(req->vwv+1, 0);
3702         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3703
3704         /*
3705          * The requested read size cannot be greater than max_send. JRA.
3706          */
3707         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3708
3709         if (numtoread > maxtoread) {
3710                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3711 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3712                         (unsigned int)numtoread, (unsigned int)maxtoread,
3713                         (unsigned int)xconn->smb1.sessions.max_send));
3714                 numtoread = maxtoread;
3715         }
3716
3717         reply_outbuf(req, 5, numtoread+3);
3718
3719         data = smb_buf(req->outbuf) + 3;
3720
3721         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3722             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3723             &lock);
3724
3725         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3726                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3727                 END_PROFILE(SMBread);
3728                 return;
3729         }
3730
3731         if (numtoread > 0)
3732                 nread = read_file(fsp,data,startpos,numtoread);
3733
3734         if (nread < 0) {
3735                 reply_nterror(req, map_nt_error_from_unix(errno));
3736                 goto strict_unlock;
3737         }
3738
3739         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3740
3741         SSVAL(req->outbuf,smb_vwv0,nread);
3742         SSVAL(req->outbuf,smb_vwv5,nread+3);
3743         SCVAL(smb_buf(req->outbuf),0,1);
3744         SSVAL(smb_buf(req->outbuf),1,nread);
3745
3746         DEBUG(3, ("read %s num=%d nread=%d\n",
3747                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3748
3749 strict_unlock:
3750         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3751
3752         END_PROFILE(SMBread);
3753         return;
3754 }
3755
3756 /****************************************************************************
3757  Setup readX header.
3758 ****************************************************************************/
3759
3760 static int setup_readX_header(struct smb_request *req, char *outbuf,
3761                               size_t smb_maxcnt)
3762 {
3763         int outsize;
3764
3765         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3766                                   False);
3767
3768         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3769
3770         SCVAL(outbuf,smb_vwv0,0xFF);
3771         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3772         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3773         SSVAL(outbuf,smb_vwv6,
3774               (smb_wct - 4)     /* offset from smb header to wct */
3775               + 1               /* the wct field */
3776               + 12 * sizeof(uint16_t) /* vwv */
3777               + 2               /* the buflen field */
3778               + 1);             /* padding byte */
3779         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3780         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3781         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3782         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3783         _smb_setlen_large(outbuf,
3784                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3785         return outsize;
3786 }
3787
3788 /****************************************************************************
3789  Reply to a read and X - possibly using sendfile.
3790 ****************************************************************************/
3791
3792 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3793                             files_struct *fsp, off_t startpos,
3794                             size_t smb_maxcnt)
3795 {
3796         struct smbXsrv_connection *xconn = req->xconn;
3797         ssize_t nread = -1;
3798         struct lock_struct lock;
3799         int saved_errno = 0;
3800
3801         init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3802             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3803             &lock);
3804
3805         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3806                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3807                 return;
3808         }
3809
3810         /*
3811          * We can only use sendfile on a non-chained packet
3812          * but we can use on a non-oplocked file. tridge proved this
3813          * on a train in Germany :-). JRA.
3814          */
3815
3816         if (!req_is_in_chain(req) &&
3817             !req->encrypted &&
3818             (fsp->base_fsp == NULL) &&
3819             (fsp->wcp == NULL) &&
3820             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3821                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3822                 DATA_BLOB header;
3823
3824                 if(fsp_stat(fsp) == -1) {
3825                         reply_nterror(req, map_nt_error_from_unix(errno));
3826                         goto strict_unlock;
3827                 }
3828
3829                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3830                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3831                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3832                         /*
3833                          * We already know that we would do a short read, so don't
3834                          * try the sendfile() path.
3835                          */
3836                         goto nosendfile_read;
3837                 }
3838
3839                 /*
3840                  * Set up the packet header before send. We
3841                  * assume here the sendfile will work (get the
3842                  * correct amount of data).
3843                  */
3844
3845                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3846
3847                 construct_reply_common_req(req, (char *)headerbuf);
3848                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3849
3850                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3851                                          startpos, smb_maxcnt);
3852                 if (nread == -1) {
3853                         saved_errno = errno;
3854
3855                         /* Returning ENOSYS means no data at all was sent.
3856                            Do this as a normal read. */
3857                         if (errno == ENOSYS) {
3858                                 goto normal_read;
3859                         }
3860
3861                         /*
3862                          * Special hack for broken Linux with no working sendfile. If we
3863                          * return EINTR we sent the header but not the rest of the data.
3864                          * Fake this up by doing read/write calls.
3865                          */
3866
3867                         if (errno == EINTR) {
3868                                 /* Ensure we don't do this again. */
3869                                 set_use_sendfile(SNUM(conn), False);
3870                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3871                                 nread = fake_sendfile(xconn, fsp, startpos,
3872                                                       smb_maxcnt);
3873                                 if (nread == -1) {
3874                                         saved_errno = errno;
3875                                         DEBUG(0,("send_file_readX: "
3876                                                  "fake_sendfile failed for "
3877                                                  "file %s (%s) for client %s. "
3878                                                  "Terminating\n",
3879                                                  fsp_str_dbg(fsp),
3880                                                  smbXsrv_connection_dbg(xconn),
3881                                                  strerror(saved_errno)));
3882                                         errno = saved_errno;
3883                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3884                                 }
3885                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3886                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3887                                 /* No outbuf here means successful sendfile. */
3888                                 goto strict_unlock;
3889                         }
3890
3891                         DEBUG(0,("send_file_readX: sendfile failed for file "
3892                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3893                                  strerror(errno)));
3894                         exit_server_cleanly("send_file_readX sendfile failed");
3895                 } else if (nread == 0) {
3896                         /*
3897                          * Some sendfile implementations return 0 to indicate
3898                          * that there was a short read, but nothing was
3899                          * actually written to the socket.  In this case,
3900                          * fallback to the normal read path so the header gets
3901                          * the correct byte count.
3902                          */
3903                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3904                                   "falling back to the normal read: %s\n",
3905                                   fsp_str_dbg(fsp)));
3906                         goto normal_read;
3907                 }
3908
3909                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3910                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3911
3912                 /* Deal with possible short send. */
3913                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3914                         ssize_t ret;
3915
3916                         ret = sendfile_short_send(xconn, fsp, nread,
3917                                                   sizeof(headerbuf), smb_maxcnt);
3918                         if (ret == -1) {
3919                                 const char *r;
3920                                 r = "send_file_readX: sendfile_short_send failed";
3921                                 DEBUG(0,("%s for file %s (%s).\n",
3922                                          r, fsp_str_dbg(fsp), strerror(errno)));
3923                                 exit_server_cleanly(r);
3924                         }
3925                 }
3926                 /* No outbuf here means successful sendfile. */
3927                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3928                 SMB_PERFCOUNT_END(&req->pcd);
3929                 goto strict_unlock;
3930         }
3931
3932 normal_read:
3933
3934         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3935                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3936                 ssize_t ret;
3937
3938                 construct_reply_common_req(req, (char *)headerbuf);
3939                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3940
3941                 /* Send out the header. */
3942                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3943                                  sizeof(headerbuf));
3944                 if (ret != sizeof(headerbuf)) {
3945                         saved_errno = errno;
3946                         /*
3947                          * Try and give an error message saying what
3948                          * client failed.
3949                          */
3950                         DEBUG(0,("send_file_readX: write_data failed for file "
3951                                  "%s (%s) for client %s. Terminating\n",
3952                                  fsp_str_dbg(fsp),
3953                                  smbXsrv_connection_dbg(xconn),
3954                                  strerror(saved_errno)));
3955                         errno = saved_errno;
3956                         exit_server_cleanly("send_file_readX sendfile failed");
3957                 }
3958                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3959                 if (nread == -1) {
3960                         saved_errno = errno;
3961                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3962                                  "%s (%s) for client %s. Terminating\n",
3963                                  fsp_str_dbg(fsp),
3964                                  smbXsrv_connection_dbg(xconn),
3965                                  strerror(saved_errno)));
3966                         errno = saved_errno;
3967                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3968                 }
3969                 goto strict_unlock;
3970         }
3971
3972 nosendfile_read:
3973
3974         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3975         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3976         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3977
3978         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3979                           startpos, smb_maxcnt);
3980         saved_errno = errno;
3981
3982         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3983
3984         if (nread < 0) {
3985                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3986                 return;
3987         }
3988
3989         setup_readX_header(req, (char *)req->outbuf, nread);
3990
3991         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3992                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3993         return;
3994
3995  strict_unlock:
3996         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3997         TALLOC_FREE(req->outbuf);
3998         return;
3999 }
4000
4001 /****************************************************************************
4002  Work out how much space we have for a read return.
4003 ****************************************************************************/
4004
4005 static size_t calc_max_read_pdu(const struct smb_request *req)
4006 {
4007         struct smbXsrv_connection *xconn = req->xconn;
4008
4009         if (xconn->protocol < PROTOCOL_NT1) {
4010                 return xconn->smb1.sessions.max_send;
4011         }
4012
4013         if (!lp_large_readwrite()) {
4014                 return xconn->smb1.sessions.max_send;
4015         }
4016
4017         if (req_is_in_chain(req)) {
4018                 return xconn->smb1.sessions.max_send;
4019         }
4020
4021         if (req->encrypted) {
4022                 /*
4023                  * Don't take encrypted traffic up to the
4024                  * limit. There are padding considerations
4025                  * that make that tricky.
4026                  */
4027                 return xconn->smb1.sessions.max_send;
4028         }
4029
4030         if (srv_is_signing_active(xconn)) {
4031                 return 0x1FFFF;
4032         }
4033
4034         if (!lp_unix_extensions()) {
4035                 return 0x1FFFF;
4036         }
4037
4038         /*
4039          * We can do ultra-large POSIX reads.
4040          */
4041         return 0xFFFFFF;
4042 }
4043
4044 /****************************************************************************
4045  Calculate how big a read can be. Copes with all clients. It's always
4046  safe to return a short read - Windows does this.
4047 ****************************************************************************/
4048
4049 static size_t calc_read_size(const struct smb_request *req,
4050                              size_t upper_size,
4051                              size_t lower_size)
4052 {
4053         struct smbXsrv_connection *xconn = req->xconn;
4054         size_t max_pdu = calc_max_read_pdu(req);
4055         size_t total_size = 0;
4056         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4057         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4058
4059         /*
4060          * Windows explicitly ignores upper size of 0xFFFF.
4061          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4062          * We must do the same as these will never fit even in
4063          * an extended size NetBIOS packet.
4064          */
4065         if (upper_size == 0xFFFF) {
4066                 upper_size = 0;
4067         }
4068
4069         if (xconn->protocol < PROTOCOL_NT1) {
4070                 upper_size = 0;
4071         }
4072
4073         total_size = ((upper_size<<16) | lower_size);
4074
4075         /*
4076          * LARGE_READX test shows it's always safe to return
4077          * a short read. Windows does so.
4078          */
4079         return MIN(total_size, max_len);
4080 }
4081
4082 /****************************************************************************
4083  Reply to a read and X.
4084 ****************************************************************************/
4085
4086 void reply_read_and_X(struct smb_request *req)
4087 {
4088         connection_struct *conn = req->conn;
4089         files_struct *fsp;
4090         off_t startpos;
4091         size_t smb_maxcnt;
4092         size_t upper_size;
4093         bool big_readX = False;
4094 #if 0
4095         size_t smb_mincnt = SVAL(req->vwv+6, 0);
4096 #endif
4097
4098         START_PROFILE(SMBreadX);
4099
4100         if ((req->wct != 10) && (req->wct != 12)) {
4101                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4102                 return;
4103         }
4104
4105         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4106         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4107         smb_maxcnt = SVAL(req->vwv+5, 0);
4108
4109         /* If it's an IPC, pass off the pipe handler. */
4110         if (IS_IPC(conn)) {
4111                 reply_pipe_read_and_X(req);
4112                 END_PROFILE(SMBreadX);
4113                 return;
4114         }
4115
4116         if (!check_fsp(conn, req, fsp)) {
4117                 END_PROFILE(SMBreadX);
4118                 return;
4119         }
4120
4121         if (!CHECK_READ(fsp,req)) {
4122                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4123                 END_PROFILE(SMBreadX);
4124                 return;
4125         }
4126
4127         upper_size = SVAL(req->vwv+7, 0);
4128         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4129         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4130                 /*
4131                  * This is a heuristic to avoid keeping large
4132                  * outgoing buffers around over long-lived aio
4133                  * requests.
4134                  */
4135                 big_readX = True;
4136         }
4137
4138         if (req->wct == 12) {
4139                 /*
4140                  * This is a large offset (64 bit) read.
4141                  */
4142                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4143
4144         }
4145
4146         if (!big_readX) {
4147                 NTSTATUS status = schedule_aio_read_and_X(conn,
4148                                         req,
4149                                         fsp,
4150                                         startpos,
4151                                         smb_maxcnt);
4152                 if (NT_STATUS_IS_OK(status)) {
4153                         /* Read scheduled - we're done. */
4154                         goto out;
4155                 }
4156                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4157                         /* Real error - report to client. */
4158                         END_PROFILE(SMBreadX);
4159                         reply_nterror(req, status);
4160                         return;
4161                 }
4162                 /* NT_STATUS_RETRY - fall back to sync read. */
4163         }
4164
4165         smbd_lock_socket(req->xconn);
4166         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4167         smbd_unlock_socket(req->xconn);
4168
4169  out:
4170         END_PROFILE(SMBreadX);
4171         return;
4172 }
4173
4174 /****************************************************************************
4175  Error replies to writebraw must have smb_wct == 1. Fix this up.
4176 ****************************************************************************/
4177
4178 void error_to_writebrawerr(struct smb_request *req)
4179 {
4180         uint8_t *old_outbuf = req->outbuf;
4181
4182         reply_outbuf(req, 1, 0);
4183
4184         memcpy(req->outbuf, old_outbuf, smb_size);
4185         TALLOC_FREE(old_outbuf);
4186 }
4187
4188 /****************************************************************************
4189  Read 4 bytes of a smb packet and return the smb length of the packet.
4190  Store the result in the buffer. This version of the function will
4191  never return a session keepalive (length of zero).
4192  Timeout is in milliseconds.
4193 ****************************************************************************/
4194
4195 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4196                                 size_t *len)
4197 {
4198         uint8_t msgtype = NBSSkeepalive;
4199
4200         while (msgtype == NBSSkeepalive) {
4201                 NTSTATUS status;
4202
4203                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4204                                                           len);
4205                 if (!NT_STATUS_IS_OK(status)) {
4206                         char addr[INET6_ADDRSTRLEN];
4207                         /* Try and give an error message
4208                          * saying what client failed. */
4209                         DEBUG(0, ("read_fd_with_timeout failed for "
4210                                   "client %s read error = %s.\n",
4211                                   get_peer_addr(fd,addr,sizeof(addr)),
4212                                   nt_errstr(status)));
4213                         return status;
4214                 }
4215
4216                 msgtype = CVAL(inbuf, 0);
4217         }
4218
4219         DEBUG(10,("read_smb_length: got smb length of %lu\n",
4220                   (unsigned long)len));
4221
4222         return NT_STATUS_OK;
4223 }
4224
4225 /****************************************************************************
4226  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4227 ****************************************************************************/
4228
4229 void reply_writebraw(struct smb_request *req)
4230 {
4231         connection_struct *conn = req->conn;
4232         struct smbXsrv_connection *xconn = req->xconn;
4233         char *buf = NULL;
4234         ssize_t nwritten=0;
4235         ssize_t total_written=0;
4236         size_t numtowrite=0;
4237         size_t tcount;
4238         off_t startpos;
4239         const char *data=NULL;
4240         bool write_through;
4241         files_struct *fsp;
4242         struct lock_struct lock;
4243         NTSTATUS status;
4244
4245         START_PROFILE(SMBwritebraw);
4246
4247         /*
4248          * If we ever reply with an error, it must have the SMB command
4249          * type of SMBwritec, not SMBwriteBraw, as this tells the client
4250          * we're finished.
4251          */
4252         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4253
4254         if (srv_is_signing_active(xconn)) {
4255                 END_PROFILE(SMBwritebraw);
4256                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4257                                 "raw reads/writes are disallowed.");
4258         }
4259
4260         if (req->wct < 12) {
4261                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4262                 error_to_writebrawerr(req);
4263                 END_PROFILE(SMBwritebraw);
4264                 return;
4265         }
4266
4267         if (xconn->smb1.echo_handler.trusted_fde) {
4268                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4269                          "'async smb echo handler = yes'\n"));
4270                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4271                 error_to_writebrawerr(req);
4272                 END_PROFILE(SMBwritebraw);
4273                 return;
4274         }
4275
4276         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4277         if (!check_fsp(conn, req, fsp)) {
4278                 error_to_writebrawerr(req);
4279                 END_PROFILE(SMBwritebraw);
4280                 return;
4281         }
4282
4283         if (!CHECK_WRITE(fsp)) {
4284                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4285                 error_to_writebrawerr(req);
4286                 END_PROFILE(SMBwritebraw);
4287                 return;
4288         }
4289
4290         tcount = IVAL(req->vwv+1, 0);
4291         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4292         write_through = BITSETW(req->vwv+7,0);
4293
4294         /* We have to deal with slightly different formats depending
4295                 on whether we are using the core+ or lanman1.0 protocol */
4296
4297         if(get_Protocol() <= PROTOCOL_COREPLUS) {
4298                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4299                 data = smb_buf_const(req->inbuf);
4300         } else {
4301                 numtowrite = SVAL(req->vwv+10, 0);
4302                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4303         }
4304
4305         /* Ensure we don't write bytes past the end of this packet. */
4306         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4307                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4308                 error_to_writebrawerr(req);
4309                 END_PROFILE(SMBwritebraw);
4310                 return;
4311         }
4312
4313         if (!fsp->print_file) {
4314                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4315                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4316                     &lock);
4317
4318                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4319                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4320                         error_to_writebrawerr(req);
4321                         END_PROFILE(SMBwritebraw);
4322                         return;
4323                 }
4324         }
4325
4326         if (numtowrite>0) {
4327                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4328         }
4329
4330         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4331                         "wrote=%d sync=%d\n",
4332                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4333                 (int)nwritten, (int)write_through));
4334
4335         if (nwritten < (ssize_t)numtowrite)  {
4336                 reply_nterror(req, NT_STATUS_DISK_FULL);
4337                 error_to_writebrawerr(req);
4338                 goto strict_unlock;
4339         }
4340
4341         total_written = nwritten;
4342
4343         /* Allocate a buffer of 64k + length. */
4344         buf = talloc_array(NULL, char, 65540);
4345         if (!buf) {
4346                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4347                 error_to_writebrawerr(req);
4348                 goto strict_unlock;
4349         }
4350
4351         /* Return a SMBwritebraw message to the redirector to tell
4352          * it to send more bytes */
4353
4354         memcpy(buf, req->inbuf, smb_size);
4355         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4356         SCVAL(buf,smb_com,SMBwritebraw);
4357         SSVALS(buf,smb_vwv0,0xFFFF);
4358         show_msg(buf);
4359         if (!srv_send_smb(req->xconn,
4360                           buf,
4361                           false, 0, /* no signing */
4362                           IS_CONN_ENCRYPTED(conn),
4363                           &req->pcd)) {
4364                 exit_server_cleanly("reply_writebraw: srv_send_smb "
4365                         "failed.");
4366         }
4367
4368         /* Now read the raw data into the buffer and write it */
4369         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4370                                  &numtowrite);
4371         if (!NT_STATUS_IS_OK(status)) {
4372                 exit_server_cleanly("secondary writebraw failed");
4373         }
4374
4375         /* Set up outbuf to return the correct size */
4376         reply_outbuf(req, 1, 0);
4377
4378         if (numtowrite != 0) {
4379
4380                 if (numtowrite > 0xFFFF) {
4381                         DEBUG(0,("reply_writebraw: Oversize secondary write "
4382                                 "raw requested (%u). Terminating\n",
4383                                 (unsigned int)numtowrite ));
4384                         exit_server_cleanly("secondary writebraw failed");
4385                 }
4386
4387                 if (tcount > nwritten+numtowrite) {
4388                         DEBUG(3,("reply_writebraw: Client overestimated the "
4389                                 "write %d %d %d\n",
4390                                 (int)tcount,(int)nwritten,(int)numtowrite));
4391                 }
4392
4393                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4394                                             numtowrite);
4395
4396                 if (!NT_STATUS_IS_OK(status)) {
4397                         /* Try and give an error message
4398                          * saying what client failed. */
4399                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
4400                                   "raw read failed (%s) for client %s. "
4401                                   "Terminating\n", nt_errstr(status),
4402                                   smbXsrv_connection_dbg(xconn)));
4403                         exit_server_cleanly("secondary writebraw failed");
4404                 }
4405
4406                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4407                 if (nwritten == -1) {
4408                         TALLOC_FREE(buf);
4409                         reply_nterror(req, map_nt_error_from_unix(errno));
4410                         error_to_writebrawerr(req);
4411                         goto strict_unlock;
4412                 }
4413
4414                 if (nwritten < (ssize_t)numtowrite) {
4415                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
4416                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
4417                 }
4418
4419                 if (nwritten > 0) {
4420                         total_written += nwritten;
4421                 }
4422         }
4423
4424         TALLOC_FREE(buf);
4425         SSVAL(req->outbuf,smb_vwv0,total_written);
4426
4427         status = sync_file(conn, fsp, write_through);
4428         if (!NT_STATUS_IS_OK(status)) {
4429                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4430                          fsp_str_dbg(fsp), nt_errstr(status)));
4431                 reply_nterror(req, status);
4432                 error_to_writebrawerr(req);
4433                 goto strict_unlock;
4434         }
4435
4436         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4437                 "wrote=%d\n",
4438                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4439                 (int)total_written));
4440
4441         if (!fsp->print_file) {
4442                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4443         }
4444
4445         /* We won't return a status if write through is not selected - this
4446          * follows what WfWg does */
4447         END_PROFILE(SMBwritebraw);
4448
4449         if (!write_through && total_written==tcount) {
4450
4451 #if RABBIT_PELLET_FIX
4452                 /*
4453                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4454                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4455                  * JRA.
4456                  */
4457                 if (!send_keepalive(xconn->transport.sock)) {
4458                         exit_server_cleanly("reply_writebraw: send of "
4459                                 "keepalive failed");
4460                 }
4461 #endif
4462                 TALLOC_FREE(req->outbuf);
4463         }
4464         return;
4465
4466 strict_unlock:
4467         if (!fsp->print_file) {
4468                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4469         }
4470
4471         END_PROFILE(SMBwritebraw);
4472         return;
4473 }
4474
4475 #undef DBGC_CLASS
4476 #define DBGC_CLASS DBGC_LOCKING
4477
4478 /****************************************************************************
4479  Reply to a writeunlock (core+).
4480 ****************************************************************************/
4481
4482 void reply_writeunlock(struct smb_request *req)
4483 {
4484         connection_struct *conn = req->conn;
4485         ssize_t nwritten = -1;
4486         size_t numtowrite;
4487         off_t startpos;
4488         const char *data;
4489         NTSTATUS status = NT_STATUS_OK;
4490         files_struct *fsp;
4491         struct lock_struct lock;
4492         int saved_errno = 0;
4493
4494         START_PROFILE(SMBwriteunlock);
4495
4496         if (req->wct < 5) {
4497                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4498                 END_PROFILE(SMBwriteunlock);
4499                 return;
4500         }
4501
4502         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4503
4504         if (!check_fsp(conn, req, fsp)) {
4505                 END_PROFILE(SMBwriteunlock);
4506                 return;
4507         }
4508
4509         if (!CHECK_WRITE(fsp)) {
4510                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4511                 END_PROFILE(SMBwriteunlock);
4512                 return;
4513         }
4514
4515         numtowrite = SVAL(req->vwv+1, 0);
4516         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4517         data = (const char *)req->buf + 3;
4518
4519         if (!fsp->print_file && numtowrite > 0) {
4520                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4521                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4522                     &lock);
4523
4524                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4525                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4526                         END_PROFILE(SMBwriteunlock);
4527                         return;
4528                 }
4529         }
4530
4531         /* The special X/Open SMB protocol handling of
4532            zero length writes is *NOT* done for
4533            this call */
4534         if(numtowrite == 0) {
4535                 nwritten = 0;
4536         } else {
4537                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4538                 saved_errno = errno;
4539         }
4540
4541         status = sync_file(conn, fsp, False /* write through */);
4542         if (!NT_STATUS_IS_OK(status)) {
4543                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4544                          fsp_str_dbg(fsp), nt_errstr(status)));
4545                 reply_nterror(req, status);
4546                 goto strict_unlock;
4547         }
4548
4549         if(nwritten < 0) {
4550                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4551                 goto strict_unlock;
4552         }
4553
4554         if((nwritten < numtowrite) && (numtowrite != 0)) {
4555                 reply_nterror(req, NT_STATUS_DISK_FULL);
4556                 goto strict_unlock;
4557         }
4558
4559         if (numtowrite && !fsp->print_file) {
4560                 status = do_unlock(req->sconn->msg_ctx,
4561                                 fsp,
4562                                 (uint64_t)req->smbpid,
4563                                 (uint64_t)numtowrite, 
4564                                 (uint64_t)startpos,
4565                                 WINDOWS_LOCK);
4566
4567                 if (NT_STATUS_V(status)) {
4568                         reply_nterror(req, status);
4569                         goto strict_unlock;
4570                 }
4571         }
4572
4573         reply_outbuf(req, 1, 0);
4574
4575         SSVAL(req->outbuf,smb_vwv0,nwritten);
4576
4577         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4578                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4579
4580 strict_unlock:
4581         if (numtowrite && !fsp->print_file) {
4582                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4583         }
4584
4585         END_PROFILE(SMBwriteunlock);
4586         return;
4587 }
4588
4589 #undef DBGC_CLASS
4590 #define DBGC_CLASS DBGC_ALL
4591
4592 /****************************************************************************
4593  Reply to a write.
4594 ****************************************************************************/
4595
4596 void reply_write(struct smb_request *req)
4597 {
4598         connection_struct *conn = req->conn;
4599         size_t numtowrite;
4600         ssize_t nwritten = -1;
4601         off_t startpos;
4602         const char *data;
4603         files_struct *fsp;
4604         struct lock_struct lock;
4605         NTSTATUS status;
4606         int saved_errno = 0;
4607
4608         START_PROFILE(SMBwrite);
4609
4610         if (req->wct < 5) {
4611                 END_PROFILE(SMBwrite);
4612                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4613                 return;
4614         }
4615
4616         /* If it's an IPC, pass off the pipe handler. */
4617         if (IS_IPC(conn)) {
4618                 reply_pipe_write(req);
4619                 END_PROFILE(SMBwrite);
4620                 return;
4621         }
4622
4623         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4624
4625         if (!check_fsp(conn, req, fsp)) {
4626                 END_PROFILE(SMBwrite);
4627                 return;
4628         }
4629
4630         if (!CHECK_WRITE(fsp)) {
4631                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4632                 END_PROFILE(SMBwrite);
4633                 return;
4634         }
4635
4636         numtowrite = SVAL(req->vwv+1, 0);
4637         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4638         data = (const char *)req->buf + 3;
4639
4640         if (!fsp->print_file) {
4641                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4642                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4643                         &lock);
4644
4645                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4646                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4647                         END_PROFILE(SMBwrite);
4648                         return;
4649                 }
4650         }
4651
4652         /*
4653          * X/Open SMB protocol says that if smb_vwv1 is
4654          * zero then the file size should be extended or
4655          * truncated to the size given in smb_vwv[2-3].
4656          */
4657
4658         if(numtowrite == 0) {
4659                 /*
4660                  * This is actually an allocate call, and set EOF. JRA.
4661                  */
4662                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4663                 if (nwritten < 0) {
4664                         reply_nterror(req, NT_STATUS_DISK_FULL);
4665                         goto strict_unlock;
4666                 }
4667                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4668                 if (nwritten < 0) {
4669                         reply_nterror(req, NT_STATUS_DISK_FULL);
4670                         goto strict_unlock;
4671                 }
4672                 trigger_write_time_update_immediate(fsp);
4673         } else {
4674                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4675         }
4676
4677         status = sync_file(conn, fsp, False);
4678         if (!NT_STATUS_IS_OK(status)) {
4679                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4680                          fsp_str_dbg(fsp), nt_errstr(status)));
4681                 reply_nterror(req, status);
4682                 goto strict_unlock;
4683         }
4684
4685         if(nwritten < 0) {
4686                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4687                 goto strict_unlock;
4688         }
4689
4690         if((nwritten == 0) && (numtowrite != 0)) {
4691                 reply_nterror(req, NT_STATUS_DISK_FULL);
4692                 goto strict_unlock;
4693         }
4694
4695         reply_outbuf(req, 1, 0);
4696
4697         SSVAL(req->outbuf,smb_vwv0,nwritten);
4698
4699         if (nwritten < (ssize_t)numtowrite) {
4700                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4701                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4702         }
4703
4704         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4705
4706 strict_unlock:
4707         if (!fsp->print_file) {
4708                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4709         }
4710
4711         END_PROFILE(SMBwrite);
4712         return;
4713 }
4714
4715 /****************************************************************************
4716  Ensure a buffer is a valid writeX for recvfile purposes.
4717 ****************************************************************************/
4718
4719 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4720                                                 (2*14) + /* word count (including bcc) */ \
4721                                                 1 /* pad byte */)
4722
4723 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4724                             const uint8_t *inbuf)
4725 {
4726         size_t numtowrite;
4727         unsigned int doff = 0;
4728         size_t len = smb_len_large(inbuf);
4729         uint16_t fnum;
4730         struct smbXsrv_open *op = NULL;
4731         struct files_struct *fsp = NULL;
4732         NTSTATUS status;
4733
4734         if (is_encrypted_packet(inbuf)) {
4735                 /* Can't do this on encrypted
4736                  * connections. */
4737                 return false;
4738         }
4739
4740         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4741                 return false;
4742         }
4743
4744         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4745                         CVAL(inbuf,smb_wct) != 14) {
4746                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4747                         "invalid word length.\n"));
4748                 return false;
4749         }
4750
4751         fnum = SVAL(inbuf, smb_vwv2);
4752         status = smb1srv_open_lookup(xconn,
4753                                      fnum,
4754                                      0, /* now */
4755                                      &op);
4756         if (!NT_STATUS_IS_OK(status)) {
4757                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4758                 return false;
4759         }
4760         fsp = op->compat;
4761         if (fsp == NULL) {
4762                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4763                 return false;
4764         }
4765         if (fsp->conn == NULL) {
4766                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4767                 return false;
4768         }
4769
4770         if (IS_IPC(fsp->conn)) {
4771                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4772                 return false;
4773         }
4774         if (IS_PRINT(fsp->conn)) {
4775                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4776                 return false;
4777         }
4778         doff = SVAL(inbuf,smb_vwv11);
4779
4780         numtowrite = SVAL(inbuf,smb_vwv10);
4781
4782         if (len > doff && len - doff > 0xFFFF) {
4783                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4784         }
4785
4786         if (numtowrite == 0) {
4787                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4788                 return false;
4789         }
4790
4791         /* Ensure the sizes match up. */
4792         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4793                 /* no pad byte...old smbclient :-( */
4794                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4795                         (unsigned int)doff,
4796                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4797                 return false;
4798         }
4799
4800         if (len - doff != numtowrite) {
4801                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4802                         "len = %u, doff = %u, numtowrite = %u\n",
4803                         (unsigned int)len,
4804                         (unsigned int)doff,
4805                         (unsigned int)numtowrite ));
4806                 return false;
4807         }
4808
4809         DEBUG(10,("is_valid_writeX_buffer: true "
4810                 "len = %u, doff = %u, numtowrite = %u\n",
4811                 (unsigned int)len,
4812                 (unsigned int)doff,
4813                 (unsigned int)numtowrite ));
4814
4815         return true;
4816 }
4817
4818 /****************************************************************************
4819  Reply to a write and X.
4820 ****************************************************************************/
4821
4822 void reply_write_and_X(struct smb_request *req)
4823 {
4824         connection_struct *conn = req->conn;
4825         struct smbXsrv_connection *xconn = req->xconn;
4826         files_struct *fsp;
4827         struct lock_struct lock;
4828         off_t startpos;
4829         size_t numtowrite;
4830         bool write_through;
4831         ssize_t nwritten;
4832         unsigned int smb_doff;
4833         unsigned int smblen;
4834         const char *data;
4835         NTSTATUS status;
4836         int saved_errno = 0;
4837
4838         START_PROFILE(SMBwriteX);
4839
4840         if ((req->wct != 12) && (req->wct != 14)) {
4841                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4842                 goto out;
4843         }
4844
4845         numtowrite = SVAL(req->vwv+10, 0);
4846         smb_doff = SVAL(req->vwv+11, 0);
4847         smblen = smb_len(req->inbuf);
4848
4849         if (req->unread_bytes > 0xFFFF ||
4850                         (smblen > smb_doff &&
4851                                 smblen - smb_doff > 0xFFFF)) {
4852                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4853         }
4854
4855         if (req->unread_bytes) {
4856                 /* Can't do a recvfile write on IPC$ */
4857                 if (IS_IPC(conn)) {
4858                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4859                         goto out;
4860                 }
4861                 if (numtowrite != req->unread_bytes) {
4862                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4863                         goto out;
4864                 }
4865         } else {
4866                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4867                                 smb_doff + numtowrite > smblen) {
4868                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4869                         goto out;
4870                 }
4871         }
4872
4873         /* If it's an IPC, pass off the pipe handler. */
4874         if (IS_IPC(conn)) {
4875                 if (req->unread_bytes) {
4876                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4877                         goto out;
4878                 }
4879                 reply_pipe_write_and_X(req);
4880                 goto out;
4881         }
4882
4883         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4884         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4885         write_through = BITSETW(req->vwv+7,0);
4886
4887         if (!check_fsp(conn, req, fsp)) {
4888                 goto out;
4889         }
4890
4891         if (!CHECK_WRITE(fsp)) {
4892                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4893                 goto out;
4894         }
4895
4896         data = smb_base(req->inbuf) + smb_doff;
4897
4898         if(req->wct == 14) {
4899                 /*
4900                  * This is a large offset (64 bit) write.
4901                  */
4902                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4903
4904         }
4905
4906         /* X/Open SMB protocol says that, unlike SMBwrite
4907         if the length is zero then NO truncation is
4908         done, just a write of zero. To truncate a file,
4909         use SMBwrite. */
4910
4911         if(numtowrite == 0) {
4912                 nwritten = 0;
4913         } else {
4914                 if (req->unread_bytes == 0) {
4915                         status = schedule_aio_write_and_X(conn,
4916                                                 req,
4917                                                 fsp,
4918                                                 data,
4919                                                 startpos,
4920                                                 numtowrite);
4921
4922                         if (NT_STATUS_IS_OK(status)) {
4923                                 /* write scheduled - we're done. */
4924                                 goto out;
4925                         }
4926                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4927                                 /* Real error - report to client. */
4928                                 reply_nterror(req, status);
4929                                 goto out;
4930                         }
4931                         /* NT_STATUS_RETRY - fall through to sync write. */
4932                 }
4933
4934                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4935                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4936                     &lock);
4937
4938                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4939                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4940                         goto out;
4941                 }
4942
4943                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4944                 saved_errno = errno;
4945
4946                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4947         }
4948
4949         if(nwritten < 0) {
4950                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4951                 goto out;
4952         }
4953
4954         if((nwritten == 0) && (numtowrite != 0)) {
4955                 reply_nterror(req, NT_STATUS_DISK_FULL);
4956                 goto out;
4957         }
4958
4959         reply_outbuf(req, 6, 0);
4960         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4961         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4962         SSVAL(req->outbuf,smb_vwv2,nwritten);
4963         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4964
4965         DEBUG(3,("writeX %s num=%d wrote=%d\n",
4966                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4967
4968         status = sync_file(conn, fsp, write_through);
4969         if (!NT_STATUS_IS_OK(status)) {
4970                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4971                          fsp_str_dbg(fsp), nt_errstr(status)));
4972                 reply_nterror(req, status);
4973                 goto out;
4974         }
4975
4976         END_PROFILE(SMBwriteX);
4977         return;
4978
4979 out:
4980         if (req->unread_bytes) {
4981                 /* writeX failed. drain socket. */
4982                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4983                                 req->unread_bytes) {
4984                         smb_panic("failed to drain pending bytes");
4985                 }
4986                 req->unread_bytes = 0;
4987         }
4988
4989         END_PROFILE(SMBwriteX);
4990         return;
4991 }
4992
4993 /****************************************************************************
4994  Reply to a lseek.
4995 ****************************************************************************/
4996
4997 void reply_lseek(struct smb_request *req)
4998 {
4999         connection_struct *conn = req->conn;
5000         off_t startpos;
5001         off_t res= -1;
5002         int mode,umode;
5003         files_struct *fsp;
5004
5005         START_PROFILE(SMBlseek);
5006
5007         if (req->wct < 4) {
5008                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5009                 END_PROFILE(SMBlseek);
5010                 return;
5011         }
5012
5013         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5014
5015         if (!check_fsp(conn, req, fsp)) {
5016                 return;
5017         }
5018
5019         flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5020
5021         mode = SVAL(req->vwv+1, 0) & 3;
5022         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5023         startpos = (off_t)IVALS(req->vwv+2, 0);
5024
5025         switch (mode) {
5026                 case 0:
5027                         umode = SEEK_SET;
5028                         res = startpos;
5029                         break;
5030                 case 1:
5031                         umode = SEEK_CUR;
5032                         res = fsp->fh->pos + startpos;
5033                         break;
5034                 case 2:
5035                         umode = SEEK_END;
5036                         break;
5037                 default:
5038                         umode = SEEK_SET;
5039                         res = startpos;
5040                         break;
5041         }
5042
5043         if (umode == SEEK_END) {
5044                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5045                         if(errno == EINVAL) {
5046                                 off_t current_pos = startpos;
5047
5048                                 if(fsp_stat(fsp) == -1) {
5049                                         reply_nterror(req,
5050                                                 map_nt_error_from_unix(errno));
5051                                         END_PROFILE(SMBlseek);
5052                                         return;
5053                                 }
5054
5055                                 current_pos += fsp->fsp_name->st.st_ex_size;
5056                                 if(current_pos < 0)
5057                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5058                         }
5059                 }
5060
5061                 if(res == -1) {
5062                         reply_nterror(req, map_nt_error_from_unix(errno));
5063                         END_PROFILE(SMBlseek);
5064                         return;
5065                 }
5066         }
5067
5068         fsp->fh->pos = res;
5069
5070         reply_outbuf(req, 2, 0);
5071         SIVAL(req->outbuf,smb_vwv0,res);
5072
5073         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5074                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5075
5076         END_PROFILE(SMBlseek);
5077         return;
5078 }
5079
5080 /****************************************************************************
5081  Reply to a flush.
5082 ****************************************************************************/
5083
5084 void reply_flush(struct smb_request *req)
5085 {
5086         connection_struct *conn = req->conn;
5087         uint16_t fnum;
5088         files_struct *fsp;
5089
5090         START_PROFILE(SMBflush);
5091
5092         if (req->wct < 1) {
5093                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5094                 return;
5095         }
5096
5097         fnum = SVAL(req->vwv+0, 0);
5098         fsp = file_fsp(req, fnum);
5099
5100         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5101                 return;
5102         }
5103
5104         if (!fsp) {
5105                 file_sync_all(conn);
5106         } else {
5107                 NTSTATUS status = sync_file(conn, fsp, True);
5108                 if (!NT_STATUS_IS_OK(status)) {
5109                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5110                                 fsp_str_dbg(fsp), nt_errstr(status)));
5111                         reply_nterror(req, status);
5112                         END_PROFILE(SMBflush);
5113                         return;
5114                 }
5115         }
5116
5117         reply_outbuf(req, 0, 0);
5118
5119         DEBUG(3,("flush\n"));
5120         END_PROFILE(SMBflush);
5121         return;
5122 }
5123
5124 /****************************************************************************
5125  Reply to a exit.
5126  conn POINTER CAN BE NULL HERE !
5127 ****************************************************************************/
5128
5129 void reply_exit(struct smb_request *req)
5130 {
5131         START_PROFILE(SMBexit);
5132
5133         file_close_pid(req->sconn, req->smbpid, req->vuid);
5134
5135         reply_outbuf(req, 0, 0);
5136
5137         DEBUG(3,("exit\n"));
5138
5139         END_PROFILE(SMBexit);
5140         return;
5141 }
5142
5143 struct reply_close_state {
5144         files_struct *fsp;
5145         struct smb_request *smbreq;
5146 };
5147
5148 static void do_smb1_close(struct tevent_req *req);
5149
5150 void reply_close(struct smb_request *req)
5151 {
5152         connection_struct *conn = req->conn;
5153         NTSTATUS status = NT_STATUS_OK;
5154         files_struct *fsp = NULL;
5155         START_PROFILE(SMBclose);
5156
5157         if (req->wct < 3) {
5158                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5159                 END_PROFILE(SMBclose);
5160                 return;
5161         }
5162
5163         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5164
5165         /*
5166          * We can only use check_fsp if we know it's not a directory.
5167          */
5168
5169         if (!check_fsp_open(conn, req, fsp)) {
5170                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5171                 END_PROFILE(SMBclose);
5172                 return;
5173         }
5174
5175         DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5176                   fsp->is_directory ? "directory" : "file",
5177                   fsp->fh->fd, fsp_fnum_dbg(fsp),
5178                   conn->num_files_open));
5179
5180         if (!fsp->is_directory) {
5181                 time_t t;
5182
5183                 /*
5184                  * Take care of any time sent in the close.
5185                  */
5186
5187                 t = srv_make_unix_date3(req->vwv+1);
5188                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5189         }
5190
5191         if (fsp->num_aio_requests != 0) {
5192
5193                 struct reply_close_state *state;
5194
5195                 DEBUG(10, ("closing with aio %u requests pending\n",
5196                            fsp->num_aio_requests));
5197
5198                 /*
5199                  * We depend on the aio_extra destructor to take care of this
5200                  * close request once fsp->num_aio_request drops to 0.
5201                  */
5202
5203                 fsp->deferred_close = tevent_wait_send(
5204                         fsp, fsp->conn->sconn->ev_ctx);
5205                 if (fsp->deferred_close == NULL) {
5206                         status = NT_STATUS_NO_MEMORY;
5207                         goto done;
5208                 }
5209
5210                 state = talloc(fsp, struct reply_close_state);
5211                 if (state == NULL) {
5212                         TALLOC_FREE(fsp->deferred_close);
5213                         status = NT_STATUS_NO_MEMORY;
5214                         goto done;
5215                 }
5216                 state->fsp = fsp;
5217                 state->smbreq = talloc_move(fsp, &req);
5218                 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5219                                         state);
5220                 END_PROFILE(SMBclose);
5221                 return;
5222         }
5223
5224         /*
5225          * close_file() returns the unix errno if an error was detected on
5226          * close - normally this is due to a disk full error. If not then it
5227          * was probably an I/O error.
5228          */
5229
5230         status = close_file(req, fsp, NORMAL_CLOSE);
5231 done:
5232         if (!NT_STATUS_IS_OK(status)) {
5233                 reply_nterror(req, status);
5234                 END_PROFILE(SMBclose);
5235                 return;
5236         }
5237
5238         reply_outbuf(req, 0, 0);
5239         END_PROFILE(SMBclose);
5240         return;
5241 }
5242
5243 static void do_smb1_close(struct tevent_req *req)
5244 {
5245         struct reply_close_state *state = tevent_req_callback_data(
5246                 req, struct reply_close_state);
5247         struct smb_request *smbreq;
5248         NTSTATUS status;
5249         int ret;
5250
5251         ret = tevent_wait_recv(req);
5252         TALLOC_FREE(req);
5253         if (ret != 0) {
5254                 DEBUG(10, ("tevent_wait_recv returned %s\n",
5255                            strerror(ret)));
5256                 /*
5257                  * Continue anyway, this should never happen
5258                  */
5259         }
5260
5261         /*
5262          * fsp->smb2_close_request right now is a talloc grandchild of
5263          * fsp. When we close_file(fsp), it would go with it. No chance to
5264          * reply...
5265          */
5266         smbreq = talloc_move(talloc_tos(), &state->smbreq);
5267
5268         status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5269         if (NT_STATUS_IS_OK(status)) {
5270                 reply_outbuf(smbreq, 0, 0);
5271         } else {
5272                 reply_nterror(smbreq, status);
5273         }
5274         if (!srv_send_smb(smbreq->xconn,
5275                         (char *)smbreq->outbuf,
5276                         true,
5277                         smbreq->seqnum+1,
5278                         IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5279                         NULL)) {
5280                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5281                                     "failed.");
5282         }
5283         TALLOC_FREE(smbreq);
5284 }
5285
5286 /****************************************************************************
5287  Reply to a writeclose (Core+ protocol).
5288 ****************************************************************************/
5289
5290 void reply_writeclose(struct smb_request *req)
5291 {
5292         connection_struct *conn = req->conn;
5293         size_t numtowrite;
5294         ssize_t nwritten = -1;
5295         NTSTATUS close_status = NT_STATUS_OK;
5296         off_t startpos;
5297         const char *data;
5298         struct timespec mtime;
5299         files_struct *fsp;
5300         struct lock_struct lock;
5301
5302         START_PROFILE(SMBwriteclose);
5303
5304         if (req->wct < 6) {
5305                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5306                 END_PROFILE(SMBwriteclose);
5307                 return;
5308         }
5309
5310         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5311
5312         if (!check_fsp(conn, req, fsp)) {
5313                 END_PROFILE(SMBwriteclose);
5314                 return;
5315         }
5316         if (!CHECK_WRITE(fsp)) {
5317                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5318                 END_PROFILE(SMBwriteclose);
5319                 return;
5320         }
5321
5322         numtowrite = SVAL(req->vwv+1, 0);
5323         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5324         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5325         data = (const char *)req->buf + 1;
5326
5327         if (fsp->print_file == NULL) {
5328                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5329                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5330                     &lock);
5331
5332                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5333                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5334                         END_PROFILE(SMBwriteclose);
5335                         return;
5336                 }
5337         }
5338
5339         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5340
5341         if (fsp->print_file == NULL) {
5342                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5343         }
5344
5345         set_close_write_time(fsp, mtime);
5346
5347         /*
5348          * More insanity. W2K only closes the file if writelen > 0.
5349          * JRA.
5350          */
5351
5352         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5353                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5354                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5355
5356         if (numtowrite) {
5357                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5358                          "file %s\n", fsp_str_dbg(fsp)));
5359                 close_status = close_file(req, fsp, NORMAL_CLOSE);
5360                 fsp = NULL;
5361         }
5362
5363         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5364                 reply_nterror(req, NT_STATUS_DISK_FULL);
5365                 goto out;
5366         }
5367
5368         if(!NT_STATUS_IS_OK(close_status)) {
5369                 reply_nterror(req, close_status);
5370                 goto out;
5371         }
5372
5373         reply_outbuf(req, 1, 0);
5374
5375         SSVAL(req->outbuf,smb_vwv0,nwritten);
5376
5377 out:
5378
5379         END_PROFILE(SMBwriteclose);
5380         return;
5381 }
5382
5383 #undef DBGC_CLASS
5384 #define DBGC_CLASS DBGC_LOCKING
5385
5386 /****************************************************************************
5387  Reply to a lock.
5388 ****************************************************************************/
5389
5390 void reply_lock(struct smb_request *req)
5391 {
5392         connection_struct *conn = req->conn;
5393         uint64_t count,offset;
5394         NTSTATUS status;
5395         files_struct *fsp;
5396         struct byte_range_lock *br_lck = NULL;
5397
5398         START_PROFILE(SMBlock);
5399
5400         if (req->wct < 5) {
5401                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5402                 END_PROFILE(SMBlock);
5403                 return;
5404         }
5405
5406         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5407
5408         if (!check_fsp(conn, req, fsp)) {
5409                 END_PROFILE(SMBlock);
5410                 return;
5411         }
5412
5413         count = (uint64_t)IVAL(req->vwv+1, 0);
5414         offset = (uint64_t)IVAL(req->vwv+3, 0);
5415
5416         DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5417                  fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5418
5419         br_lck = do_lock(req->sconn->msg_ctx,
5420                         fsp,
5421                         (uint64_t)req->smbpid,
5422                         count,
5423                         offset,
5424                         WRITE_LOCK,
5425                         WINDOWS_LOCK,
5426                         False, /* Non-blocking lock. */
5427                         &status,
5428                         NULL);
5429
5430         TALLOC_FREE(br_lck);
5431
5432         if (NT_STATUS_V(status)) {
5433                 reply_nterror(req, status);
5434                 END_PROFILE(SMBlock);
5435                 return;
5436         }
5437
5438         reply_outbuf(req, 0, 0);
5439
5440         END_PROFILE(SMBlock);
5441         return;
5442 }
5443
5444 /****************************************************************************
5445  Reply to a unlock.
5446 ****************************************************************************/
5447
5448 void reply_unlock(struct smb_request *req)
5449 {
5450         connection_struct *conn = req->conn;
5451         uint64_t count,offset;
5452         NTSTATUS status;
5453         files_struct *fsp;
5454
5455         START_PROFILE(SMBunlock);
5456
5457         if (req->wct < 5) {
5458                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5459                 END_PROFILE(SMBunlock);
5460                 return;
5461         }
5462
5463         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5464
5465         if (!check_fsp(conn, req, fsp)) {
5466                 END_PROFILE(SMBunlock);
5467                 return;
5468         }
5469
5470         count = (uint64_t)IVAL(req->vwv+1, 0);
5471         offset = (uint64_t)IVAL(req->vwv+3, 0);
5472
5473         status = do_unlock(req->sconn->msg_ctx,
5474                         fsp,
5475                         (uint64_t)req->smbpid,
5476                         count,
5477                         offset,
5478                         WINDOWS_LOCK);
5479
5480         if (NT_STATUS_V(status)) {
5481                 reply_nterror(req, status);
5482                 END_PROFILE(SMBunlock);
5483                 return;
5484         }
5485
5486         DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5487                     fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5488
5489         reply_outbuf(req, 0, 0);
5490
5491         END_PROFILE(SMBunlock);
5492         return;
5493 }
5494
5495 #undef DBGC_CLASS
5496 #define DBGC_CLASS DBGC_ALL
5497
5498 /****************************************************************************
5499  Reply to a tdis.
5500  conn POINTER CAN BE NULL HERE !
5501 ****************************************************************************/
5502
5503 void reply_tdis(struct smb_request *req)
5504 {
5505         NTSTATUS status;
5506         connection_struct *conn = req->conn;
5507         struct smbXsrv_tcon *tcon;
5508
5509         START_PROFILE(SMBtdis);
5510
5511         if (!conn) {
5512                 DEBUG(4,("Invalid connection in tdis\n"));
5513                 reply_force_doserror(req, ERRSRV, ERRinvnid);
5514                 END_PROFILE(SMBtdis);
5515                 return;
5516         }
5517
5518         tcon = conn->tcon;
5519         req->conn = NULL;
5520
5521         /*
5522          * TODO: cancel all outstanding requests on the tcon
5523          */
5524         status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5525         if (!NT_STATUS_IS_OK(status)) {
5526                 DEBUG(0, ("reply_tdis: "
5527                           "smbXsrv_tcon_disconnect() failed: %s\n",
5528                           nt_errstr(status)));
5529                 /*
5530                  * If we hit this case, there is something completely
5531                  * wrong, so we better disconnect the transport connection.
5532                  */
5533                 END_PROFILE(SMBtdis);
5534                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5535                 return;
5536         }
5537
5538         TALLOC_FREE(tcon);
5539
5540         reply_outbuf(req, 0, 0);
5541         END_PROFILE(SMBtdis);
5542         return;
5543 }
5544
5545 /****************************************************************************
5546  Reply to a echo.
5547  conn POINTER CAN BE NULL HERE !
5548 ****************************************************************************/
5549
5550 void reply_echo(struct smb_request *req)
5551 {
5552         connection_struct *conn = req->conn;
5553         struct smb_perfcount_data local_pcd;
5554         struct smb_perfcount_data *cur_pcd;
5555         int smb_reverb;
5556         int seq_num;
5557
5558         START_PROFILE(SMBecho);
5559
5560         smb_init_perfcount_data(&local_pcd);
5561
5562         if (req->wct < 1) {
5563                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5564                 END_PROFILE(SMBecho);
5565                 return;
5566         }
5567
5568         smb_reverb = SVAL(req->vwv+0, 0);
5569
5570         reply_outbuf(req, 1, req->buflen);
5571
5572         /* copy any incoming data back out */
5573         if (req->buflen > 0) {
5574                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5575         }
5576
5577         if (smb_reverb > 100) {
5578                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5579                 smb_reverb = 100;
5580         }
5581
5582         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5583
5584                 /* this makes sure we catch the request pcd */
5585                 if (seq_num == smb_reverb) {
5586                         cur_pcd = &req->pcd;
5587                 } else {
5588                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5589                         cur_pcd = &local_pcd;
5590                 }
5591
5592                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5593
5594                 show_msg((char *)req->outbuf);
5595                 if (!srv_send_smb(req->xconn,
5596                                 (char *)req->outbuf,
5597                                 true, req->seqnum+1,
5598                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5599                                 cur_pcd))
5600                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5601         }
5602
5603         DEBUG(3,("echo %d times\n", smb_reverb));
5604
5605         TALLOC_FREE(req->outbuf);
5606
5607         END_PROFILE(SMBecho);
5608         return;
5609 }
5610
5611 /****************************************************************************
5612  Reply to a printopen.
5613 ****************************************************************************/
5614
5615 void reply_printopen(struct smb_request *req)
5616 {
5617         connection_struct *conn = req->conn;
5618         files_struct *fsp;
5619         NTSTATUS status;
5620
5621         START_PROFILE(SMBsplopen);
5622
5623         if (req->wct < 2) {
5624                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5625                 END_PROFILE(SMBsplopen);
5626                 return;
5627         }
5628
5629         if (!CAN_PRINT(conn)) {
5630                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5631                 END_PROFILE(SMBsplopen);
5632                 return;
5633         }
5634
5635         status = file_new(req, conn, &fsp);
5636         if(!NT_STATUS_IS_OK(status)) {
5637                 reply_nterror(req, status);
5638                 END_PROFILE(SMBsplopen);
5639                 return;
5640         }
5641
5642         /* Open for exclusive use, write only. */
5643         status = print_spool_open(fsp, NULL, req->vuid);
5644
5645         if (!NT_STATUS_IS_OK(status)) {
5646                 file_free(req, fsp);
5647                 reply_nterror(req, status);
5648                 END_PROFILE(SMBsplopen);
5649                 return;
5650         }
5651
5652         reply_outbuf(req, 1, 0);
5653         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5654
5655         DEBUG(3,("openprint fd=%d %s\n",
5656                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5657
5658         END_PROFILE(SMBsplopen);
5659         return;
5660 }
5661
5662 /****************************************************************************
5663  Reply to a printclose.
5664 ****************************************************************************/
5665
5666 void reply_printclose(struct smb_request *req)
5667 {
5668         connection_struct *conn = req->conn;
5669         files_struct *fsp;
5670         NTSTATUS status;
5671
5672         START_PROFILE(SMBsplclose);
5673
5674         if (req->wct < 1) {
5675                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5676                 END_PROFILE(SMBsplclose);
5677                 return;
5678         }
5679
5680         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5681
5682         if (!check_fsp(conn, req, fsp)) {
5683                 END_PROFILE(SMBsplclose);
5684                 return;
5685         }
5686
5687         if (!CAN_PRINT(conn)) {
5688                 reply_force_doserror(req, ERRSRV, ERRerror);
5689                 END_PROFILE(SMBsplclose);
5690                 return;
5691         }
5692
5693         DEBUG(3,("printclose fd=%d %s\n",
5694                  fsp->fh->fd, fsp_fnum_dbg(fsp)));
5695
5696         status = close_file(req, fsp, NORMAL_CLOSE);
5697
5698         if(!NT_STATUS_IS_OK(status)) {
5699                 reply_nterror(req, status);
5700                 END_PROFILE(SMBsplclose);
5701                 return;
5702         }
5703
5704         reply_outbuf(req, 0, 0);
5705
5706         END_PROFILE(SMBsplclose);
5707         return;
5708 }
5709
5710 /****************************************************************************
5711  Reply to a printqueue.
5712 ****************************************************************************/
5713
5714 void reply_printqueue(struct smb_request *req)
5715 {
5716         connection_struct *conn = req->conn;
5717         int max_count;
5718         int start_index;
5719
5720         START_PROFILE(SMBsplretq);
5721
5722         if (req->wct < 2) {
5723                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5724                 END_PROFILE(SMBsplretq);
5725                 return;
5726         }
5727
5728         max_count = SVAL(req->vwv+0, 0);
5729         start_index = SVAL(req->vwv+1, 0);
5730
5731         /* we used to allow the client to get the cnum wrong, but that
5732            is really quite gross and only worked when there was only
5733            one printer - I think we should now only accept it if they
5734            get it right (tridge) */
5735         if (!CAN_PRINT(conn)) {
5736                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5737                 END_PROFILE(SMBsplretq);
5738                 return;
5739         }
5740
5741         reply_outbuf(req, 2, 3);
5742         SSVAL(req->outbuf,smb_vwv0,0);
5743         SSVAL(req->outbuf,smb_vwv1,0);
5744         SCVAL(smb_buf(req->outbuf),0,1);
5745         SSVAL(smb_buf(req->outbuf),1,0);
5746
5747         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5748                  start_index, max_count));
5749
5750         {
5751                 TALLOC_CTX *mem_ctx = talloc_tos();
5752                 NTSTATUS status;
5753                 WERROR werr;
5754                 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5755                 struct rpc_pipe_client *cli = NULL;
5756                 struct dcerpc_binding_handle *b = NULL;
5757                 struct policy_handle handle;
5758                 struct spoolss_DevmodeContainer devmode_ctr;
5759                 union spoolss_JobInfo *info;
5760                 uint32_t count;
5761                 uint32_t num_to_get;
5762                 uint32_t first;
5763                 uint32_t i;
5764
5765                 ZERO_STRUCT(handle);
5766
5767                 status = rpc_pipe_open_interface(conn,
5768                                                  &ndr_table_spoolss,
5769                                                  conn->session_info,
5770                                                  conn->sconn->remote_address,
5771                                                  conn->sconn->msg_ctx,
5772                                                  &cli);
5773                 if (!NT_STATUS_IS_OK(status)) {
5774                         DEBUG(0, ("reply_printqueue: "
5775                                   "could not connect to spoolss: %s\n",
5776                                   nt_errstr(status)));
5777                         reply_nterror(req, status);
5778                         goto out;
5779                 }
5780                 b = cli->binding_handle;
5781
5782                 ZERO_STRUCT(devmode_ctr);
5783
5784                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5785                                                 sharename,
5786                                                 NULL, devmode_ctr,
5787                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5788                                                 &handle,
5789                                                 &werr);
5790                 if (!NT_STATUS_IS_OK(status)) {
5791                         reply_nterror(req, status);
5792                         goto out;
5793                 }
5794                 if (!W_ERROR_IS_OK(werr)) {
5795                         reply_nterror(req, werror_to_ntstatus(werr));
5796                         goto out;
5797                 }
5798
5799                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5800                                                &handle,
5801                                                0, /* firstjob */
5802                                                0xff, /* numjobs */
5803                                                2, /* level */
5804                                                0, /* offered */
5805                                                &count,
5806                                                &info);
5807                 if (!W_ERROR_IS_OK(werr)) {
5808                         reply_nterror(req, werror_to_ntstatus(werr));
5809                         goto out;
5810                 }
5811
5812                 if (max_count > 0) {
5813                         first = start_index;
5814                 } else {
5815                         first = start_index + max_count + 1;
5816                 }
5817
5818                 if (first >= count) {
5819                         num_to_get = first;
5820                 } else {
5821                         num_to_get = first + MIN(ABS(max_count), count - first);
5822                 }
5823
5824                 for (i = first; i < num_to_get; i++) {
5825                         char blob[28];
5826                         char *p = blob;
5827                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5828                         int qstatus;
5829                         size_t len = 0;
5830                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5831                                                         info[i].info2.job_id);
5832
5833                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5834                                 qstatus = 2;
5835                         } else {
5836                                 qstatus = 3;
5837                         }
5838
5839                         srv_put_dos_date2(p, 0, qtime);
5840                         SCVAL(p, 4, qstatus);
5841                         SSVAL(p, 5, qrapjobid);
5842                         SIVAL(p, 7, info[i].info2.size);
5843                         SCVAL(p, 11, 0);
5844                         status = srvstr_push(blob, req->flags2, p+12,
5845                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
5846                         if (!NT_STATUS_IS_OK(status)) {
5847                                 reply_nterror(req, status);
5848                                 goto out;
5849                         }
5850                         if (message_push_blob(
5851                                     &req->outbuf,
5852                                     data_blob_const(
5853                                             blob, sizeof(blob))) == -1) {
5854                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5855                                 goto out;
5856                         }
5857                 }
5858
5859                 if (count > 0) {
5860                         SSVAL(req->outbuf,smb_vwv0,count);
5861                         SSVAL(req->outbuf,smb_vwv1,
5862                               (max_count>0?first+count:first-1));
5863                         SCVAL(smb_buf(req->outbuf),0,1);
5864                         SSVAL(smb_buf(req->outbuf),1,28*count);
5865                 }
5866
5867
5868                 DEBUG(3, ("%u entries returned in queue\n",
5869                           (unsigned)count));
5870
5871 out:
5872                 if (b && is_valid_policy_hnd(&handle)) {
5873                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5874                 }
5875
5876         }
5877
5878         END_PROFILE(SMBsplretq);
5879         return;
5880 }
5881
5882 /****************************************************************************
5883  Reply to a printwrite.
5884 ****************************************************************************/
5885
5886 void reply_printwrite(struct smb_request *req)
5887 {
5888         connection_struct *conn = req->conn;
5889         int numtowrite;
5890         const char *data;
5891         files_struct *fsp;
5892
5893         START_PROFILE(SMBsplwr);
5894
5895         if (req->wct < 1) {
5896                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5897                 END_PROFILE(SMBsplwr);
5898                 return;
5899         }
5900
5901         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5902
5903         if (!check_fsp(conn, req, fsp)) {
5904                 END_PROFILE(SMBsplwr);
5905                 return;
5906         }
5907
5908         if (!fsp->print_file) {
5909                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5910                 END_PROFILE(SMBsplwr);
5911                 return;
5912         }
5913
5914         if (!CHECK_WRITE(fsp)) {
5915                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5916                 END_PROFILE(SMBsplwr);
5917                 return;
5918         }
5919
5920         numtowrite = SVAL(req->buf, 1);
5921
5922         if (req->buflen < numtowrite + 3) {
5923                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5924                 END_PROFILE(SMBsplwr);
5925                 return;
5926         }
5927
5928         data = (const char *)req->buf + 3;
5929
5930         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5931                 reply_nterror(req, map_nt_error_from_unix(errno));
5932                 END_PROFILE(SMBsplwr);
5933                 return;
5934         }
5935
5936         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5937
5938         END_PROFILE(SMBsplwr);
5939         return;
5940 }
5941
5942 /****************************************************************************
5943  Reply to a mkdir.
5944 ****************************************************************************/
5945
5946 void reply_mkdir(struct smb_request *req)
5947 {
5948         connection_struct *conn = req->conn;
5949         struct smb_filename *smb_dname = NULL;
5950         char *directory = NULL;
5951         NTSTATUS status;
5952         TALLOC_CTX *ctx = talloc_tos();
5953
5954         START_PROFILE(SMBmkdir);
5955
5956         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5957                             STR_TERMINATE, &status);
5958         if (!NT_STATUS_IS_OK(status)) {
5959                 reply_nterror(req, status);
5960                 goto out;
5961         }
5962
5963         status = filename_convert(ctx, conn,
5964                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5965                                  directory,
5966                                  UCF_PREP_CREATEFILE,
5967                                  NULL,
5968                                  &smb_dname);
5969         if (!NT_STATUS_IS_OK(status)) {
5970                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5971                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5972                                         ERRSRV, ERRbadpath);
5973                         goto out;
5974                 }
5975                 reply_nterror(req, status);
5976                 goto out;
5977         }
5978
5979         status = create_directory(conn, req, smb_dname);
5980
5981         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5982
5983         if (!NT_STATUS_IS_OK(status)) {
5984
5985                 if (!use_nt_status()
5986                     && NT_STATUS_EQUAL(status,
5987                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5988                         /*
5989                          * Yes, in the DOS error code case we get a
5990                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5991                          * samba4 torture test.
5992                          */
5993                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5994                 }
5995
5996                 reply_nterror(req, status);
5997                 goto out;
5998         }
5999
6000         reply_outbuf(req, 0, 0);
6001
6002         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6003  out:
6004         TALLOC_FREE(smb_dname);
6005         END_PROFILE(SMBmkdir);
6006         return;
6007 }
6008
6009 /****************************************************************************
6010  Reply to a rmdir.
6011 ****************************************************************************/
6012
6013 void reply_rmdir(struct smb_request *req)
6014 {
6015         connection_struct *conn = req->conn;
6016         struct smb_filename *smb_dname = NULL;
6017         char *directory = NULL;
6018         NTSTATUS status;
6019         TALLOC_CTX *ctx = talloc_tos();
6020         files_struct *fsp = NULL;
6021         int info = 0;
6022         struct smbd_server_connection *sconn = req->sconn;
6023
6024         START_PROFILE(SMBrmdir);
6025
6026         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6027                             STR_TERMINATE, &status);
6028         if (!NT_STATUS_IS_OK(status)) {
6029                 reply_nterror(req, status);
6030                 goto out;
6031         }
6032
6033         status = filename_convert(ctx, conn,
6034                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
6035                                  directory,
6036                                  0,
6037                                  NULL,
6038                                  &smb_dname);
6039         if (!NT_STATUS_IS_OK(status)) {
6040                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6041                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6042                                         ERRSRV, ERRbadpath);
6043                         goto out;
6044                 }
6045                 reply_nterror(req, status);
6046                 goto out;
6047         }
6048
6049         if (is_ntfs_stream_smb_fname(smb_dname)) {
6050                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6051                 goto out;
6052         }
6053
6054         status = SMB_VFS_CREATE_FILE(
6055                 conn,                                   /* conn */
6056                 req,                                    /* req */
6057                 0,                                      /* root_dir_fid */
6058                 smb_dname,                              /* fname */
6059                 DELETE_ACCESS,                          /* access_mask */
6060                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6061                         FILE_SHARE_DELETE),
6062                 FILE_OPEN,                              /* create_disposition*/
6063                 FILE_DIRECTORY_FILE,                    /* create_options */
6064                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6065                 0,                                      /* oplock_request */
6066                 NULL,                                   /* lease */
6067                 0,                                      /* allocation_size */
6068                 0,                                      /* private_flags */
6069                 NULL,                                   /* sd */
6070                 NULL,                                   /* ea_list */
6071                 &fsp,                                   /* result */
6072                 &info,                                  /* pinfo */
6073                 NULL, NULL);                            /* create context */
6074
6075         if (!NT_STATUS_IS_OK(status)) {
6076                 if (open_was_deferred(req->xconn, req->mid)) {
6077                         /* We have re-scheduled this call. */
6078                         goto out;
6079                 }
6080                 reply_nterror(req, status);
6081                 goto out;
6082         }
6083
6084         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6085         if (!NT_STATUS_IS_OK(status)) {
6086                 close_file(req, fsp, ERROR_CLOSE);
6087                 reply_nterror(req, status);
6088                 goto out;
6089         }
6090
6091         if (!set_delete_on_close(fsp, true,
6092                         conn->session_info->security_token,
6093                         conn->session_info->unix_token)) {
6094                 close_file(req, fsp, ERROR_CLOSE);
6095                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6096                 goto out;
6097         }
6098
6099         status = close_file(req, fsp, NORMAL_CLOSE);
6100         if (!NT_STATUS_IS_OK(status)) {
6101                 reply_nterror(req, status);
6102         } else {
6103                 reply_outbuf(req, 0, 0);
6104         }
6105
6106         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6107
6108         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6109  out:
6110         TALLOC_FREE(smb_dname);
6111         END_PROFILE(SMBrmdir);
6112         return;
6113 }
6114
6115 /*******************************************************************
6116  Resolve wildcards in a filename rename.
6117 ********************************************************************/
6118
6119 static bool resolve_wildcards(TALLOC_CTX *ctx,
6120                                 const char *name1,
6121                                 const char *name2,
6122                                 char **pp_newname)
6123 {
6124         char *name2_copy = NULL;
6125         char *root1 = NULL;
6126         char *root2 = NULL;
6127         char *ext1 = NULL;
6128         char *ext2 = NULL;
6129         char *p,*p2, *pname1, *pname2;
6130
6131         name2_copy = talloc_strdup(ctx, name2);
6132         if (!name2_copy) {
6133                 return False;
6134         }
6135
6136         pname1 = strrchr_m(name1,'/');
6137         pname2 = strrchr_m(name2_copy,'/');
6138
6139         if (!pname1 || !pname2) {
6140                 return False;
6141         }
6142
6143         /* Truncate the copy of name2 at the last '/' */
6144         *pname2 = '\0';
6145
6146         /* Now go past the '/' */
6147         pname1++;
6148         pname2++;
6149
6150         root1 = talloc_strdup(ctx, pname1);
6151         root2 = talloc_strdup(ctx, pname2);
6152
6153         if (!root1 || !root2) {
6154                 return False;
6155         }
6156
6157         p = strrchr_m(root1,'.');
6158         if (p) {
6159                 *p = 0;
6160                 ext1 = talloc_strdup(ctx, p+1);
6161         } else {
6162                 ext1 = talloc_strdup(ctx, "");
6163         }
6164         p = strrchr_m(root2,'.');
6165         if (p) {
6166                 *p = 0;
6167                 ext2 = talloc_strdup(ctx, p+1);
6168         } else {
6169                 ext2 = talloc_strdup(ctx, "");
6170         }
6171
6172         if (!ext1 || !ext2) {
6173                 return False;
6174         }
6175
6176         p = root1;
6177         p2 = root2;
6178         while (*p2) {
6179                 if (*p2 == '?') {
6180                         /* Hmmm. Should this be mb-aware ? */
6181                         *p2 = *p;
6182                         p2++;
6183                 } else if (*p2 == '*') {
6184                         *p2 = '\0';
6185                         root2 = talloc_asprintf(ctx, "%s%s",
6186                                                 root2,
6187                                                 p);
6188                         if (!root2) {
6189                                 return False;
6190                         }
6191                         break;
6192                 } else {
6193                         p2++;
6194                 }
6195                 if (*p) {
6196                         p++;
6197                 }
6198         }
6199
6200         p = ext1;
6201         p2 = ext2;
6202         while (*p2) {
6203                 if (*p2 == '?') {
6204                         /* Hmmm. Should this be mb-aware ? */
6205                         *p2 = *p;
6206                         p2++;
6207                 } else if (*p2 == '*') {
6208                         *p2 = '\0';
6209                         ext2 = talloc_asprintf(ctx, "%s%s",
6210                                                 ext2,
6211                                                 p);
6212                         if (!ext2) {
6213                                 return False;
6214                         }
6215                         break;
6216                 } else {
6217                         p2++;
6218                 }
6219                 if (*p) {
6220                         p++;
6221                 }
6222         }
6223
6224         if (*ext2) {
6225                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6226                                 name2_copy,
6227                                 root2,
6228                                 ext2);
6229         } else {
6230                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6231                                 name2_copy,
6232                                 root2);
6233         }
6234
6235         if (!*pp_newname) {
6236                 return False;
6237         }
6238
6239         return True;
6240 }
6241
6242 /****************************************************************************
6243  Ensure open files have their names updated. Updated to notify other smbd's
6244  asynchronously.
6245 ****************************************************************************/
6246
6247 static void rename_open_files(connection_struct *conn,
6248                               struct share_mode_lock *lck,
6249                               struct file_id id,
6250                               uint32_t orig_name_hash,
6251                               const struct smb_filename *smb_fname_dst)
6252 {
6253         files_struct *fsp;
6254         bool did_rename = False;
6255         NTSTATUS status;
6256         uint32_t new_name_hash = 0;
6257
6258         for(fsp = file_find_di_first(conn->sconn, id); fsp;
6259             fsp = file_find_di_next(fsp)) {
6260                 /* fsp_name is a relative path under the fsp. To change this for other
6261                    sharepaths we need to manipulate relative paths. */
6262                 /* TODO - create the absolute path and manipulate the newname
6263                    relative to the sharepath. */
6264                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6265                         continue;
6266                 }
6267                 if (fsp->name_hash != orig_name_hash) {
6268                         continue;
6269                 }
6270                 DEBUG(10, ("rename_open_files: renaming file %s "
6271                            "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6272                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6273                            smb_fname_str_dbg(smb_fname_dst)));
6274
6275                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6276                 if (NT_STATUS_IS_OK(status)) {
6277                         did_rename = True;
6278                         new_name_hash = fsp->name_hash;
6279                 }
6280         }
6281
6282         if (!did_rename) {
6283                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6284                            "for %s\n", file_id_string_tos(&id),
6285                            smb_fname_str_dbg(smb_fname_dst)));
6286         }
6287
6288         /* Send messages to all smbd's (not ourself) that the name has changed. */
6289         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6290                               orig_name_hash, new_name_hash,
6291                               smb_fname_dst);
6292
6293 }
6294
6295 /****************************************************************************
6296  We need to check if the source path is a parent directory of the destination
6297  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6298  refuse the rename with a sharing violation. Under UNIX the above call can
6299  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6300  probably need to check that the client is a Windows one before disallowing
6301  this as a UNIX client (one with UNIX extensions) can know the source is a
6302  symlink and make this decision intelligently. Found by an excellent bug
6303  report from <AndyLiebman@aol.com>.
6304 ****************************************************************************/
6305
6306 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6307                                      const struct smb_filename *smb_fname_dst)
6308 {
6309         const char *psrc = smb_fname_src->base_name;
6310         const char *pdst = smb_fname_dst->base_name;
6311         size_t slen;
6312
6313         if (psrc[0] == '.' && psrc[1] == '/') {
6314                 psrc += 2;
6315         }
6316         if (pdst[0] == '.' && pdst[1] == '/') {
6317                 pdst += 2;
6318         }
6319         if ((slen = strlen(psrc)) > strlen(pdst)) {
6320                 return False;
6321         }
6322         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6323 }
6324
6325 /*
6326  * Do the notify calls from a rename
6327  */
6328
6329 static void notify_rename(connection_struct *conn, bool is_dir,
6330                           const struct smb_filename *smb_fname_src,
6331                           const struct smb_filename *smb_fname_dst)
6332 {
6333         char *parent_dir_src = NULL;
6334         char *parent_dir_dst = NULL;
6335         uint32_t mask;
6336
6337         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6338                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6339
6340         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6341                             &parent_dir_src, NULL) ||
6342             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6343                             &parent_dir_dst, NULL)) {
6344                 goto out;
6345         }
6346
6347         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6348                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6349                              smb_fname_src->base_name);
6350                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6351                              smb_fname_dst->base_name);
6352         }
6353         else {
6354                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6355                              smb_fname_src->base_name);
6356                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6357                              smb_fname_dst->base_name);
6358         }
6359
6360         /* this is a strange one. w2k3 gives an additional event for
6361            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6362            files, but not directories */
6363         if (!is_dir) {
6364                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6365                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6366                              |FILE_NOTIFY_CHANGE_CREATION,
6367                              smb_fname_dst->base_name);
6368         }
6369  out:
6370         TALLOC_FREE(parent_dir_src);
6371         TALLOC_FREE(parent_dir_dst);
6372 }
6373
6374 /****************************************************************************
6375  Returns an error if the parent directory for a filename is open in an
6376  incompatible way.
6377 ****************************************************************************/
6378
6379 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6380                                         const struct smb_filename *smb_fname_dst_in)
6381 {
6382         char *parent_dir = NULL;
6383         struct smb_filename smb_fname_parent;
6384         struct file_id id;
6385         files_struct *fsp = NULL;
6386         int ret;
6387
6388         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6389                         &parent_dir, NULL)) {
6390                 return NT_STATUS_NO_MEMORY;
6391         }
6392         ZERO_STRUCT(smb_fname_parent);
6393         smb_fname_parent.base_name = parent_dir;
6394
6395         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6396         if (ret == -1) {
6397                 return map_nt_error_from_unix(errno);
6398         }
6399
6400         /*
6401          * We're only checking on this smbd here, mostly good
6402          * enough.. and will pass tests.
6403          */
6404
6405         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6406         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6407                         fsp = file_find_di_next(fsp)) {
6408                 if (fsp->access_mask & DELETE_ACCESS) {
6409                         return NT_STATUS_SHARING_VIOLATION;
6410                 }
6411         }
6412         return NT_STATUS_OK;
6413 }
6414
6415 /****************************************************************************
6416  Rename an open file - given an fsp.
6417 ****************************************************************************/
6418
6419 NTSTATUS rename_internals_fsp(connection_struct *conn,
6420                         files_struct *fsp,
6421                         const struct smb_filename *smb_fname_dst_in,
6422                         uint32_t attrs,
6423                         bool replace_if_exists)
6424 {
6425         TALLOC_CTX *ctx = talloc_tos();
6426         struct smb_filename *smb_fname_dst = NULL;
6427         NTSTATUS status = NT_STATUS_OK;
6428         struct share_mode_lock *lck = NULL;
6429         bool dst_exists, old_is_stream, new_is_stream;
6430
6431         status = check_name(conn, smb_fname_dst_in->base_name);
6432         if (!NT_STATUS_IS_OK(status)) {
6433                 return status;
6434         }
6435
6436         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6437         if (!NT_STATUS_IS_OK(status)) {
6438                 return status;
6439         }
6440
6441         /* Make a copy of the dst smb_fname structs */
6442
6443         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6444         if (smb_fname_dst == NULL) {
6445                 status = NT_STATUS_NO_MEMORY;
6446                 goto out;
6447         }
6448
6449         /*
6450          * Check for special case with case preserving and not
6451          * case sensitive. If the old last component differs from the original
6452          * last component only by case, then we should allow
6453          * the rename (user is trying to change the case of the
6454          * filename).
6455          */
6456         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6457             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6458             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6459                 char *last_slash;
6460                 char *fname_dst_lcomp_base_mod = NULL;
6461                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6462
6463                 /*
6464                  * Get the last component of the destination name.
6465                  */
6466                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6467                 if (last_slash) {
6468                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6469                 } else {
6470                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6471                 }
6472                 if (!fname_dst_lcomp_base_mod) {
6473                         status = NT_STATUS_NO_MEMORY;
6474                         goto out;
6475                 }
6476
6477                 /*
6478                  * Create an smb_filename struct using the original last
6479                  * component of the destination.
6480                  */
6481                 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6482                         ctx, smb_fname_dst->original_lcomp, NULL);
6483                 if (smb_fname_orig_lcomp == NULL) {
6484                         status = NT_STATUS_NO_MEMORY;
6485                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6486                         goto out;
6487                 }
6488
6489                 /* If the base names only differ by case, use original. */
6490                 if(!strcsequal(fname_dst_lcomp_base_mod,
6491                                smb_fname_orig_lcomp->base_name)) {
6492                         char *tmp;
6493                         /*
6494                          * Replace the modified last component with the
6495                          * original.
6496                          */
6497                         if (last_slash) {
6498                                 *last_slash = '\0'; /* Truncate at the '/' */
6499                                 tmp = talloc_asprintf(smb_fname_dst,
6500                                         "%s/%s",
6501                                         smb_fname_dst->base_name,
6502                                         smb_fname_orig_lcomp->base_name);
6503                         } else {
6504                                 tmp = talloc_asprintf(smb_fname_dst,
6505                                         "%s",
6506                                         smb_fname_orig_lcomp->base_name);
6507                         }
6508                         if (tmp == NULL) {
6509                                 status = NT_STATUS_NO_MEMORY;
6510                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6511                                 TALLOC_FREE(smb_fname_orig_lcomp);
6512                                 goto out;
6513                         }
6514                         TALLOC_FREE(smb_fname_dst->base_name);
6515                         smb_fname_dst->base_name = tmp;
6516                 }
6517
6518                 /* If the stream_names only differ by case, use original. */
6519                 if(!strcsequal(smb_fname_dst->stream_name,
6520                                smb_fname_orig_lcomp->stream_name)) {
6521                         char *tmp = NULL;
6522                         /* Use the original stream. */
6523                         tmp = talloc_strdup(smb_fname_dst,
6524                                             smb_fname_orig_lcomp->stream_name);
6525                         if (tmp == NULL) {
6526                                 status = NT_STATUS_NO_MEMORY;
6527                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6528                                 TALLOC_FREE(smb_fname_orig_lcomp);
6529                                 goto out;
6530                         }
6531                         TALLOC_FREE(smb_fname_dst->stream_name);
6532                         smb_fname_dst->stream_name = tmp;
6533                 }
6534                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6535                 TALLOC_FREE(smb_fname_orig_lcomp);
6536         }
6537
6538         /*
6539          * If the src and dest names are identical - including case,
6540          * don't do the rename, just return success.
6541          */
6542
6543         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6544             strcsequal(fsp->fsp_name->stream_name,
6545                        smb_fname_dst->stream_name)) {
6546                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6547                           "- returning success\n",
6548                           smb_fname_str_dbg(smb_fname_dst)));
6549                 status = NT_STATUS_OK;
6550                 goto out;
6551         }
6552
6553         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6554         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6555
6556         /* Return the correct error code if both names aren't streams. */
6557         if (!old_is_stream && new_is_stream) {
6558                 status = NT_STATUS_OBJECT_NAME_INVALID;
6559                 goto out;
6560         }
6561
6562         if (old_is_stream && !new_is_stream) {
6563                 status = NT_STATUS_INVALID_PARAMETER;
6564                 goto out;
6565         }
6566
6567         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6568
6569         if(!replace_if_exists && dst_exists) {
6570                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6571                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6572                           smb_fname_str_dbg(smb_fname_dst)));
6573                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6574                 goto out;
6575         }
6576
6577         if (dst_exists) {
6578                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6579                     &smb_fname_dst->st);
6580                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6581                                                            fileid);
6582                 /* The file can be open when renaming a stream */
6583                 if (dst_fsp && !new_is_stream) {
6584                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6585                         status = NT_STATUS_ACCESS_DENIED;
6586                         goto out;
6587                 }
6588         }
6589
6590         /* Ensure we have a valid stat struct for the source. */
6591         status = vfs_stat_fsp(fsp);
6592         if (!NT_STATUS_IS_OK(status)) {
6593                 goto out;
6594         }
6595
6596         status = can_rename(conn, fsp, attrs);
6597
6598         if (!NT_STATUS_IS_OK(status)) {
6599                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6600                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6601                           smb_fname_str_dbg(smb_fname_dst)));
6602                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6603                         status = NT_STATUS_ACCESS_DENIED;
6604                 goto out;
6605         }
6606
6607         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6608                 status = NT_STATUS_ACCESS_DENIED;
6609         }
6610
6611         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6612
6613         /*
6614          * We have the file open ourselves, so not being able to get the
6615          * corresponding share mode lock is a fatal error.
6616          */
6617
6618         SMB_ASSERT(lck != NULL);
6619
6620         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6621                 uint32_t create_options = fsp->fh->private_options;
6622
6623                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6624                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6625                           smb_fname_str_dbg(smb_fname_dst)));
6626
6627                 if (!fsp->is_directory &&
6628                     !lp_posix_pathnames() &&
6629                     (lp_map_archive(SNUM(conn)) ||
6630                     lp_store_dos_attributes(SNUM(conn)))) {
6631                         /* We must set the archive bit on the newly
6632                            renamed file. */
6633                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6634                                 uint32_t old_dosmode = dos_mode(conn,
6635                                                         smb_fname_dst);
6636                                 file_set_dosmode(conn,
6637                                         smb_fname_dst,
6638                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6639                                         NULL,
6640                                         true);
6641                         }
6642                 }
6643
6644                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6645                               smb_fname_dst);
6646
6647                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6648                                   smb_fname_dst);
6649
6650                 /*
6651                  * A rename acts as a new file create w.r.t. allowing an initial delete
6652                  * on close, probably because in Windows there is a new handle to the
6653                  * new file. If initial delete on close was requested but not
6654                  * originally set, we need to set it here. This is probably not 100% correct,
6655                  * but will work for the CIFSFS client which in non-posix mode
6656                  * depends on these semantics. JRA.
6657                  */
6658
6659                 if (create_options & FILE_DELETE_ON_CLOSE) {
6660                         status = can_set_delete_on_close(fsp, 0);
6661
6662                         if (NT_STATUS_IS_OK(status)) {
6663                                 /* Note that here we set the *inital* delete on close flag,
6664                                  * not the regular one. The magic gets handled in close. */
6665                                 fsp->initial_delete_on_close = True;
6666                         }
6667                 }
6668                 TALLOC_FREE(lck);
6669                 status = NT_STATUS_OK;
6670                 goto out;
6671         }
6672
6673         TALLOC_FREE(lck);
6674
6675         if (errno == ENOTDIR || errno == EISDIR) {
6676                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6677         } else {
6678                 status = map_nt_error_from_unix(errno);
6679         }
6680
6681         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6682                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6683                   smb_fname_str_dbg(smb_fname_dst)));
6684
6685  out:
6686         TALLOC_FREE(smb_fname_dst);
6687
6688         return status;
6689 }
6690
6691 /****************************************************************************
6692  The guts of the rename command, split out so it may be called by the NT SMB
6693  code.
6694 ****************************************************************************/
6695
6696 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6697                         connection_struct *conn,
6698                         struct smb_request *req,
6699                         struct smb_filename *smb_fname_src,
6700                         struct smb_filename *smb_fname_dst,
6701                         uint32_t attrs,
6702                         bool replace_if_exists,
6703                         bool src_has_wild,
6704                         bool dest_has_wild,
6705                         uint32_t access_mask)
6706 {
6707         char *fname_src_dir = NULL;
6708         char *fname_src_mask = NULL;
6709         int count=0;
6710         NTSTATUS status = NT_STATUS_OK;
6711         struct smb_Dir *dir_hnd = NULL;
6712         const char *dname = NULL;
6713         char *talloced = NULL;
6714         long offset = 0;
6715         int create_options = 0;
6716         bool posix_pathnames = lp_posix_pathnames();
6717         int rc;
6718
6719         /*
6720          * Split the old name into directory and last component
6721          * strings. Note that unix_convert may have stripped off a
6722          * leading ./ from both name and newname if the rename is
6723          * at the root of the share. We need to make sure either both
6724          * name and newname contain a / character or neither of them do
6725          * as this is checked in resolve_wildcards().
6726          */
6727
6728         /* Split up the directory from the filename/mask. */
6729         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6730                                       &fname_src_dir, &fname_src_mask);
6731         if (!NT_STATUS_IS_OK(status)) {
6732                 status = NT_STATUS_NO_MEMORY;
6733                 goto out;
6734         }
6735
6736         /*
6737          * We should only check the mangled cache
6738          * here if unix_convert failed. This means
6739          * that the path in 'mask' doesn't exist
6740          * on the file system and so we need to look
6741          * for a possible mangle. This patch from
6742          * Tine Smukavec <valentin.smukavec@hermes.si>.
6743          */
6744
6745         if (!VALID_STAT(smb_fname_src->st) &&
6746             mangle_is_mangled(fname_src_mask, conn->params)) {
6747                 char *new_mask = NULL;
6748                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6749                                             conn->params);
6750                 if (new_mask) {
6751                         TALLOC_FREE(fname_src_mask);
6752                         fname_src_mask = new_mask;
6753                 }
6754         }
6755
6756         if (!src_has_wild) {
6757                 files_struct *fsp;
6758
6759                 /*
6760                  * Only one file needs to be renamed. Append the mask back
6761                  * onto the directory.
6762                  */
6763                 TALLOC_FREE(smb_fname_src->base_name);
6764                 if (ISDOT(fname_src_dir)) {
6765                         /* Ensure we use canonical names on open. */
6766                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6767                                                         "%s",
6768                                                         fname_src_mask);
6769                 } else {
6770                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6771                                                         "%s/%s",
6772                                                         fname_src_dir,
6773                                                         fname_src_mask);
6774                 }
6775                 if (!smb_fname_src->base_name) {
6776                         status = NT_STATUS_NO_MEMORY;
6777                         goto out;
6778                 }
6779
6780                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6781                           "case_preserve = %d, short case preserve = %d, "
6782                           "directory = %s, newname = %s, "
6783                           "last_component_dest = %s\n",
6784                           conn->case_sensitive, conn->case_preserve,
6785                           conn->short_case_preserve,
6786                           smb_fname_str_dbg(smb_fname_src),
6787                           smb_fname_str_dbg(smb_fname_dst),
6788                           smb_fname_dst->original_lcomp));
6789
6790                 /* The dest name still may have wildcards. */
6791                 if (dest_has_wild) {
6792                         char *fname_dst_mod = NULL;
6793                         if (!resolve_wildcards(smb_fname_dst,
6794                                                smb_fname_src->base_name,
6795                                                smb_fname_dst->base_name,
6796                                                &fname_dst_mod)) {
6797                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6798                                           "%s %s failed\n",
6799                                           smb_fname_src->base_name,
6800                                           smb_fname_dst->base_name));
6801                                 status = NT_STATUS_NO_MEMORY;
6802                                 goto out;
6803                         }
6804                         TALLOC_FREE(smb_fname_dst->base_name);
6805                         smb_fname_dst->base_name = fname_dst_mod;
6806                 }
6807
6808                 ZERO_STRUCT(smb_fname_src->st);
6809                 if (posix_pathnames) {
6810                         rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6811                 } else {
6812                         rc = SMB_VFS_STAT(conn, smb_fname_src);
6813                 }
6814                 if (rc == -1) {
6815                         status = map_nt_error_from_unix_common(errno);
6816                         goto out;
6817                 }
6818
6819                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6820                         create_options |= FILE_DIRECTORY_FILE;
6821                 }
6822
6823                 status = SMB_VFS_CREATE_FILE(
6824                         conn,                           /* conn */
6825                         req,                            /* req */
6826                         0,                              /* root_dir_fid */
6827                         smb_fname_src,                  /* fname */
6828                         access_mask,                    /* access_mask */
6829                         (FILE_SHARE_READ |              /* share_access */
6830                             FILE_SHARE_WRITE),
6831                         FILE_OPEN,                      /* create_disposition*/
6832                         create_options,                 /* create_options */
6833                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6834                         0,                              /* oplock_request */
6835                         NULL,                           /* lease */
6836                         0,                              /* allocation_size */
6837                         0,                              /* private_flags */
6838                         NULL,                           /* sd */
6839                         NULL,                           /* ea_list */
6840                         &fsp,                           /* result */
6841                         NULL,                           /* pinfo */
6842                         NULL, NULL);                    /* create context */
6843
6844                 if (!NT_STATUS_IS_OK(status)) {
6845                         DEBUG(3, ("Could not open rename source %s: %s\n",
6846                                   smb_fname_str_dbg(smb_fname_src),
6847                                   nt_errstr(status)));
6848                         goto out;
6849                 }
6850
6851                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6852                                               attrs, replace_if_exists);
6853
6854                 close_file(req, fsp, NORMAL_CLOSE);
6855
6856                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6857                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6858                           smb_fname_str_dbg(smb_fname_dst)));
6859
6860                 goto out;
6861         }
6862
6863         /*
6864          * Wildcards - process each file that matches.
6865          */
6866         if (strequal(fname_src_mask, "????????.???")) {
6867                 TALLOC_FREE(fname_src_mask);
6868                 fname_src_mask = talloc_strdup(ctx, "*");
6869                 if (!fname_src_mask) {
6870                         status = NT_STATUS_NO_MEMORY;
6871                         goto out;
6872                 }
6873         }
6874
6875         status = check_name(conn, fname_src_dir);
6876         if (!NT_STATUS_IS_OK(status)) {
6877                 goto out;
6878         }
6879
6880         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6881                           attrs);
6882         if (dir_hnd == NULL) {
6883                 status = map_nt_error_from_unix(errno);
6884                 goto out;
6885         }
6886
6887         status = NT_STATUS_NO_SUCH_FILE;
6888         /*
6889          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6890          * - gentest fix. JRA
6891          */
6892
6893         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6894                                     &talloced))) {
6895                 files_struct *fsp = NULL;
6896                 char *destname = NULL;
6897                 bool sysdir_entry = False;
6898
6899                 /* Quick check for "." and ".." */
6900                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6901                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6902                                 sysdir_entry = True;
6903                         } else {
6904                                 TALLOC_FREE(talloced);
6905                                 continue;
6906                         }
6907                 }
6908
6909                 if (!is_visible_file(conn, fname_src_dir, dname,
6910                                      &smb_fname_src->st, false)) {
6911                         TALLOC_FREE(talloced);
6912                         continue;
6913                 }
6914
6915                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6916                         TALLOC_FREE(talloced);
6917                         continue;
6918                 }
6919
6920                 if (sysdir_entry) {
6921                         status = NT_STATUS_OBJECT_NAME_INVALID;
6922                         break;
6923                 }
6924
6925                 TALLOC_FREE(smb_fname_src->base_name);
6926                 if (ISDOT(fname_src_dir)) {
6927                         /* Ensure we use canonical names on open. */
6928                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6929                                                         "%s",
6930                                                         dname);
6931                 } else {
6932                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6933                                                         "%s/%s",
6934                                                         fname_src_dir,
6935                                                         dname);
6936                 }
6937                 if (!smb_fname_src->base_name) {
6938                         status = NT_STATUS_NO_MEMORY;
6939                         goto out;
6940                 }
6941
6942                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6943                                        smb_fname_dst->base_name,
6944                                        &destname)) {
6945                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6946                                   smb_fname_src->base_name, destname));
6947                         TALLOC_FREE(talloced);
6948                         continue;
6949                 }
6950                 if (!destname) {
6951                         status = NT_STATUS_NO_MEMORY;
6952                         goto out;
6953                 }
6954
6955                 TALLOC_FREE(smb_fname_dst->base_name);
6956                 smb_fname_dst->base_name = destname;
6957
6958                 ZERO_STRUCT(smb_fname_src->st);
6959                 if (posix_pathnames) {
6960                         SMB_VFS_LSTAT(conn, smb_fname_src);
6961                 } else {
6962                         SMB_VFS_STAT(conn, smb_fname_src);
6963                 }
6964
6965                 create_options = 0;
6966
6967                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6968                         create_options |= FILE_DIRECTORY_FILE;
6969                 }
6970
6971                 status = SMB_VFS_CREATE_FILE(
6972                         conn,                           /* conn */
6973                         req,                            /* req */
6974                         0,                              /* root_dir_fid */
6975                         smb_fname_src,                  /* fname */
6976                         access_mask,                    /* access_mask */
6977                         (FILE_SHARE_READ |              /* share_access */
6978                             FILE_SHARE_WRITE),
6979                         FILE_OPEN,                      /* create_disposition*/
6980                         create_options,                 /* create_options */
6981                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6982                         0,                              /* oplock_request */
6983                         NULL,                           /* lease */
6984                         0,                              /* allocation_size */
6985                         0,                              /* private_flags */
6986                         NULL,                           /* sd */
6987                         NULL,                           /* ea_list */
6988                         &fsp,                           /* result */
6989                         NULL,                           /* pinfo */
6990                         NULL, NULL);                    /* create context */
6991
6992                 if (!NT_STATUS_IS_OK(status)) {
6993                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6994                                  "returned %s rename %s -> %s\n",
6995                                  nt_errstr(status),
6996                                  smb_fname_str_dbg(smb_fname_src),
6997                                  smb_fname_str_dbg(smb_fname_dst)));
6998                         break;
6999                 }
7000
7001                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7002                                                               dname);
7003                 if (!smb_fname_dst->original_lcomp) {
7004                         status = NT_STATUS_NO_MEMORY;
7005                         goto out;
7006                 }
7007
7008                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7009                                               attrs, replace_if_exists);
7010
7011                 close_file(req, fsp, NORMAL_CLOSE);
7012
7013                 if (!NT_STATUS_IS_OK(status)) {
7014                         DEBUG(3, ("rename_internals_fsp returned %s for "
7015                                   "rename %s -> %s\n", nt_errstr(status),
7016                                   smb_fname_str_dbg(smb_fname_src),
7017                                   smb_fname_str_dbg(smb_fname_dst)));
7018                         break;
7019                 }
7020
7021                 count++;
7022
7023                 DEBUG(3,("rename_internals: doing rename on %s -> "
7024                          "%s\n", smb_fname_str_dbg(smb_fname_src),
7025                          smb_fname_str_dbg(smb_fname_src)));
7026                 TALLOC_FREE(talloced);
7027         }
7028         TALLOC_FREE(dir_hnd);
7029
7030         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7031                 status = map_nt_error_from_unix(errno);
7032         }
7033
7034  out:
7035         TALLOC_FREE(talloced);
7036         TALLOC_FREE(fname_src_dir);
7037         TALLOC_FREE(fname_src_mask);
7038         return status;
7039 }
7040
7041 /****************************************************************************
7042  Reply to a mv.
7043 ****************************************************************************/
7044
7045 void reply_mv(struct smb_request *req)
7046 {
7047         connection_struct *conn = req->conn;
7048         char *name = NULL;
7049         char *newname = NULL;
7050         const char *p;
7051         uint32_t attrs;
7052         NTSTATUS status;
7053         bool src_has_wcard = False;
7054         bool dest_has_wcard = False;
7055         TALLOC_CTX *ctx = talloc_tos();
7056         struct smb_filename *smb_fname_src = NULL;
7057         struct smb_filename *smb_fname_dst = NULL;
7058         uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
7059         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
7060         bool stream_rename = false;
7061
7062         START_PROFILE(SMBmv);
7063
7064         if (req->wct < 1) {
7065                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7066                 goto out;
7067         }
7068
7069         attrs = SVAL(req->vwv+0, 0);
7070
7071         p = (const char *)req->buf + 1;
7072         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7073                                        &status, &src_has_wcard);
7074         if (!NT_STATUS_IS_OK(status)) {
7075                 reply_nterror(req, status);
7076                 goto out;
7077         }
7078         p++;
7079         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7080                                        &status, &dest_has_wcard);
7081         if (!NT_STATUS_IS_OK(status)) {
7082                 reply_nterror(req, status);
7083                 goto out;
7084         }
7085
7086         if (!lp_posix_pathnames()) {
7087                 /* The newname must begin with a ':' if the
7088                    name contains a ':'. */
7089                 if (strchr_m(name, ':')) {
7090                         if (newname[0] != ':') {
7091                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7092                                 goto out;
7093                         }
7094                         stream_rename = true;
7095                 }
7096         }
7097
7098         status = filename_convert(ctx,
7099                                   conn,
7100                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7101                                   name,
7102                                   src_ucf_flags,
7103                                   &src_has_wcard,
7104                                   &smb_fname_src);
7105
7106         if (!NT_STATUS_IS_OK(status)) {
7107                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7108                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7109                                         ERRSRV, ERRbadpath);
7110                         goto out;
7111                 }
7112                 reply_nterror(req, status);
7113                 goto out;
7114         }
7115
7116         status = filename_convert(ctx,
7117                                   conn,
7118                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7119                                   newname,
7120                                   dst_ucf_flags,
7121                                   &dest_has_wcard,
7122                                   &smb_fname_dst);
7123
7124         if (!NT_STATUS_IS_OK(status)) {
7125                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7126                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7127                                         ERRSRV, ERRbadpath);
7128                         goto out;
7129                 }
7130                 reply_nterror(req, status);
7131                 goto out;
7132         }
7133
7134         if (stream_rename) {
7135                 /* smb_fname_dst->base_name must be the same as
7136                    smb_fname_src->base_name. */
7137                 TALLOC_FREE(smb_fname_dst->base_name);
7138                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7139                                                 smb_fname_src->base_name);
7140                 if (!smb_fname_dst->base_name) {
7141                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7142                         goto out;
7143                 }
7144         }
7145
7146         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7147                  smb_fname_str_dbg(smb_fname_dst)));
7148
7149         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7150                                   attrs, False, src_has_wcard, dest_has_wcard,
7151                                   DELETE_ACCESS);
7152         if (!NT_STATUS_IS_OK(status)) {
7153                 if (open_was_deferred(req->xconn, req->mid)) {
7154                         /* We have re-scheduled this call. */
7155                         goto out;
7156                 }
7157                 reply_nterror(req, status);
7158                 goto out;
7159         }
7160
7161         reply_outbuf(req, 0, 0);
7162  out:
7163         TALLOC_FREE(smb_fname_src);
7164         TALLOC_FREE(smb_fname_dst);
7165         END_PROFILE(SMBmv);
7166         return;
7167 }
7168
7169 /*******************************************************************
7170  Copy a file as part of a reply_copy.
7171 ******************************************************************/
7172
7173 /*
7174  * TODO: check error codes on all callers
7175  */
7176
7177 NTSTATUS copy_file(TALLOC_CTX *ctx,
7178                         connection_struct *conn,
7179                         struct smb_filename *smb_fname_src,
7180                         struct smb_filename *smb_fname_dst,
7181                         int ofun,
7182                         int count,
7183                         bool target_is_directory)
7184 {
7185         struct smb_filename *smb_fname_dst_tmp = NULL;
7186         off_t ret=-1;
7187         files_struct *fsp1,*fsp2;
7188         uint32_t dosattrs;
7189         uint32_t new_create_disposition;
7190         NTSTATUS status;
7191
7192
7193         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7194         if (smb_fname_dst_tmp == NULL) {
7195                 return NT_STATUS_NO_MEMORY;
7196         }
7197
7198         /*
7199          * If the target is a directory, extract the last component from the
7200          * src filename and append it to the dst filename
7201          */
7202         if (target_is_directory) {
7203                 const char *p;
7204
7205                 /* dest/target can't be a stream if it's a directory. */
7206                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7207
7208                 p = strrchr_m(smb_fname_src->base_name,'/');
7209                 if (p) {
7210                         p++;
7211                 } else {
7212                         p = smb_fname_src->base_name;
7213                 }
7214                 smb_fname_dst_tmp->base_name =
7215                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7216                                            p);
7217                 if (!smb_fname_dst_tmp->base_name) {
7218                         status = NT_STATUS_NO_MEMORY;
7219                         goto out;
7220                 }
7221         }
7222
7223         status = vfs_file_exist(conn, smb_fname_src);
7224         if (!NT_STATUS_IS_OK(status)) {
7225                 goto out;
7226         }
7227
7228         if (!target_is_directory && count) {
7229                 new_create_disposition = FILE_OPEN;
7230         } else {
7231                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7232                                                  0, ofun,
7233                                                  NULL, NULL,
7234                                                  &new_create_disposition,
7235                                                  NULL,
7236                                                  NULL)) {
7237                         status = NT_STATUS_INVALID_PARAMETER;
7238                         goto out;
7239                 }
7240         }
7241
7242         /* Open the src file for reading. */
7243         status = SMB_VFS_CREATE_FILE(
7244                 conn,                                   /* conn */
7245                 NULL,                                   /* req */
7246                 0,                                      /* root_dir_fid */
7247                 smb_fname_src,                          /* fname */
7248                 FILE_GENERIC_READ,                      /* access_mask */
7249                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7250                 FILE_OPEN,                              /* create_disposition*/
7251                 0,                                      /* create_options */
7252                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7253                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7254                 NULL,                                   /* lease */
7255                 0,                                      /* allocation_size */
7256                 0,                                      /* private_flags */
7257                 NULL,                                   /* sd */
7258                 NULL,                                   /* ea_list */
7259                 &fsp1,                                  /* result */
7260                 NULL,                                   /* psbuf */
7261                 NULL, NULL);                            /* create context */
7262
7263         if (!NT_STATUS_IS_OK(status)) {
7264                 goto out;
7265         }
7266
7267         dosattrs = dos_mode(conn, smb_fname_src);
7268
7269         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7270                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7271         }
7272
7273         /* Open the dst file for writing. */
7274         status = SMB_VFS_CREATE_FILE(
7275                 conn,                                   /* conn */
7276                 NULL,                                   /* req */
7277                 0,                                      /* root_dir_fid */
7278                 smb_fname_dst,                          /* fname */
7279                 FILE_GENERIC_WRITE,                     /* access_mask */
7280                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7281                 new_create_disposition,                 /* create_disposition*/
7282                 0,                                      /* create_options */
7283                 dosattrs,                               /* file_attributes */
7284                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7285                 NULL,                                   /* lease */
7286                 0,                                      /* allocation_size */
7287                 0,                                      /* private_flags */
7288                 NULL,                                   /* sd */
7289                 NULL,                                   /* ea_list */
7290                 &fsp2,                                  /* result */
7291                 NULL,                                   /* psbuf */
7292                 NULL, NULL);                            /* create context */
7293
7294         if (!NT_STATUS_IS_OK(status)) {
7295                 close_file(NULL, fsp1, ERROR_CLOSE);
7296                 goto out;
7297         }
7298
7299         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7300                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7301                 if (ret == -1) {
7302                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7303                                 strerror(errno)));
7304                         status = map_nt_error_from_unix(errno);
7305                         close_file(NULL, fsp1, ERROR_CLOSE);
7306                         close_file(NULL, fsp2, ERROR_CLOSE);
7307                         goto out;
7308                 }
7309         }
7310
7311         /* Do the actual copy. */
7312         if (smb_fname_src->st.st_ex_size) {
7313                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7314         } else {
7315                 ret = 0;
7316         }
7317
7318         close_file(NULL, fsp1, NORMAL_CLOSE);
7319
7320         /* Ensure the modtime is set correctly on the destination file. */
7321         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7322
7323         /*
7324          * As we are opening fsp1 read-only we only expect
7325          * an error on close on fsp2 if we are out of space.
7326          * Thus we don't look at the error return from the
7327          * close of fsp1.
7328          */
7329         status = close_file(NULL, fsp2, NORMAL_CLOSE);
7330
7331         if (!NT_STATUS_IS_OK(status)) {
7332                 goto out;
7333         }
7334
7335         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7336                 status = NT_STATUS_DISK_FULL;
7337                 goto out;
7338         }
7339
7340         status = NT_STATUS_OK;
7341
7342  out:
7343         TALLOC_FREE(smb_fname_dst_tmp);
7344         return status;
7345 }
7346
7347 /****************************************************************************
7348  Reply to a file copy.
7349 ****************************************************************************/
7350
7351 void reply_copy(struct smb_request *req)
7352 {
7353         connection_struct *conn = req->conn;
7354         struct smb_filename *smb_fname_src = NULL;
7355         struct smb_filename *smb_fname_dst = NULL;
7356         char *fname_src = NULL;
7357         char *fname_dst = NULL;
7358         char *fname_src_mask = NULL;
7359         char *fname_src_dir = NULL;
7360         const char *p;
7361         int count=0;
7362         int error = ERRnoaccess;
7363         int tid2;
7364         int ofun;
7365         int flags;
7366         bool target_is_directory=False;
7367         bool source_has_wild = False;
7368         bool dest_has_wild = False;
7369         NTSTATUS status;
7370         TALLOC_CTX *ctx = talloc_tos();
7371
7372         START_PROFILE(SMBcopy);
7373
7374         if (req->wct < 3) {
7375                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7376                 goto out;
7377         }
7378
7379         tid2 = SVAL(req->vwv+0, 0);
7380         ofun = SVAL(req->vwv+1, 0);
7381         flags = SVAL(req->vwv+2, 0);
7382
7383         p = (const char *)req->buf;
7384         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7385                                        &status, &source_has_wild);
7386         if (!NT_STATUS_IS_OK(status)) {
7387                 reply_nterror(req, status);
7388                 goto out;
7389         }
7390         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7391                                        &status, &dest_has_wild);
7392         if (!NT_STATUS_IS_OK(status)) {
7393                 reply_nterror(req, status);
7394                 goto out;
7395         }
7396
7397         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7398
7399         if (tid2 != conn->cnum) {
7400                 /* can't currently handle inter share copies XXXX */
7401                 DEBUG(3,("Rejecting inter-share copy\n"));
7402                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7403                 goto out;
7404         }
7405
7406         status = filename_convert(ctx, conn,
7407                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7408                                   fname_src,
7409                                   UCF_COND_ALLOW_WCARD_LCOMP,
7410                                   &source_has_wild,
7411                                   &smb_fname_src);
7412         if (!NT_STATUS_IS_OK(status)) {
7413                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7414                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7415                                         ERRSRV, ERRbadpath);
7416                         goto out;
7417                 }
7418                 reply_nterror(req, status);
7419                 goto out;
7420         }
7421
7422         status = filename_convert(ctx, conn,
7423                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7424                                   fname_dst,
7425                                   UCF_COND_ALLOW_WCARD_LCOMP,
7426                                   &dest_has_wild,
7427                                   &smb_fname_dst);
7428         if (!NT_STATUS_IS_OK(status)) {
7429                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7430                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7431                                         ERRSRV, ERRbadpath);
7432                         goto out;
7433                 }
7434                 reply_nterror(req, status);
7435                 goto out;
7436         }
7437
7438         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7439
7440         if ((flags&1) && target_is_directory) {
7441                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7442                 goto out;
7443         }
7444
7445         if ((flags&2) && !target_is_directory) {
7446                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7447                 goto out;
7448         }
7449
7450         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7451                 /* wants a tree copy! XXXX */
7452                 DEBUG(3,("Rejecting tree copy\n"));
7453                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454                 goto out;
7455         }
7456
7457         /* Split up the directory from the filename/mask. */
7458         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7459                                       &fname_src_dir, &fname_src_mask);
7460         if (!NT_STATUS_IS_OK(status)) {
7461                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7462                 goto out;
7463         }
7464
7465         /*
7466          * We should only check the mangled cache
7467          * here if unix_convert failed. This means
7468          * that the path in 'mask' doesn't exist
7469          * on the file system and so we need to look
7470          * for a possible mangle. This patch from
7471          * Tine Smukavec <valentin.smukavec@hermes.si>.
7472          */
7473         if (!VALID_STAT(smb_fname_src->st) &&
7474             mangle_is_mangled(fname_src_mask, conn->params)) {
7475                 char *new_mask = NULL;
7476                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7477                                             &new_mask, conn->params);
7478
7479                 /* Use demangled name if one was successfully found. */
7480                 if (new_mask) {
7481                         TALLOC_FREE(fname_src_mask);
7482                         fname_src_mask = new_mask;
7483                 }
7484         }
7485
7486         if (!source_has_wild) {
7487
7488                 /*
7489                  * Only one file needs to be copied. Append the mask back onto
7490                  * the directory.
7491                  */
7492                 TALLOC_FREE(smb_fname_src->base_name);
7493                 if (ISDOT(fname_src_dir)) {
7494                         /* Ensure we use canonical names on open. */
7495                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7496                                                         "%s",
7497                                                         fname_src_mask);
7498                 } else {
7499                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7500                                                         "%s/%s",
7501                                                         fname_src_dir,
7502                                                         fname_src_mask);
7503                 }
7504                 if (!smb_fname_src->base_name) {
7505                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7506                         goto out;
7507                 }
7508
7509                 if (dest_has_wild) {
7510                         char *fname_dst_mod = NULL;
7511                         if (!resolve_wildcards(smb_fname_dst,
7512                                                smb_fname_src->base_name,
7513                                                smb_fname_dst->base_name,
7514                                                &fname_dst_mod)) {
7515                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7516                                 goto out;
7517                         }
7518                         TALLOC_FREE(smb_fname_dst->base_name);
7519                         smb_fname_dst->base_name = fname_dst_mod;
7520                 }
7521
7522                 status = check_name(conn, smb_fname_src->base_name);
7523                 if (!NT_STATUS_IS_OK(status)) {
7524                         reply_nterror(req, status);
7525                         goto out;
7526                 }
7527
7528                 status = check_name(conn, smb_fname_dst->base_name);
7529                 if (!NT_STATUS_IS_OK(status)) {
7530                         reply_nterror(req, status);
7531                         goto out;
7532                 }
7533
7534                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7535                                    ofun, count, target_is_directory);
7536
7537                 if(!NT_STATUS_IS_OK(status)) {
7538                         reply_nterror(req, status);
7539                         goto out;
7540                 } else {
7541                         count++;
7542                 }
7543         } else {
7544                 struct smb_Dir *dir_hnd = NULL;
7545                 const char *dname = NULL;
7546                 char *talloced = NULL;
7547                 long offset = 0;
7548
7549                 /*
7550                  * There is a wildcard that requires us to actually read the
7551                  * src dir and copy each file matching the mask to the dst.
7552                  * Right now streams won't be copied, but this could
7553                  * presumably be added with a nested loop for reach dir entry.
7554                  */
7555                 SMB_ASSERT(!smb_fname_src->stream_name);
7556                 SMB_ASSERT(!smb_fname_dst->stream_name);
7557
7558                 smb_fname_src->stream_name = NULL;
7559                 smb_fname_dst->stream_name = NULL;
7560
7561                 if (strequal(fname_src_mask,"????????.???")) {
7562                         TALLOC_FREE(fname_src_mask);
7563                         fname_src_mask = talloc_strdup(ctx, "*");
7564                         if (!fname_src_mask) {
7565                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7566                                 goto out;
7567                         }
7568                 }
7569
7570                 status = check_name(conn, fname_src_dir);
7571                 if (!NT_STATUS_IS_OK(status)) {
7572                         reply_nterror(req, status);
7573                         goto out;
7574                 }
7575
7576                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7577                 if (dir_hnd == NULL) {
7578                         status = map_nt_error_from_unix(errno);
7579                         reply_nterror(req, status);
7580                         goto out;
7581                 }
7582
7583                 error = ERRbadfile;
7584
7585                 /* Iterate over the src dir copying each entry to the dst. */
7586                 while ((dname = ReadDirName(dir_hnd, &offset,
7587                                             &smb_fname_src->st, &talloced))) {
7588                         char *destname = NULL;
7589
7590                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7591                                 TALLOC_FREE(talloced);
7592                                 continue;
7593                         }
7594
7595                         if (!is_visible_file(conn, fname_src_dir, dname,
7596                                              &smb_fname_src->st, false)) {
7597                                 TALLOC_FREE(talloced);
7598                                 continue;
7599                         }
7600
7601                         if(!mask_match(dname, fname_src_mask,
7602                                        conn->case_sensitive)) {
7603                                 TALLOC_FREE(talloced);
7604                                 continue;
7605                         }
7606
7607                         error = ERRnoaccess;
7608
7609                         /* Get the src smb_fname struct setup. */
7610                         TALLOC_FREE(smb_fname_src->base_name);
7611                         if (ISDOT(fname_src_dir)) {
7612                                 /* Ensure we use canonical names on open. */
7613                                 smb_fname_src->base_name =
7614                                         talloc_asprintf(smb_fname_src, "%s",
7615                                                 dname);
7616                         } else {
7617                                 smb_fname_src->base_name =
7618                                         talloc_asprintf(smb_fname_src, "%s/%s",
7619                                                 fname_src_dir, dname);
7620                         }
7621
7622                         if (!smb_fname_src->base_name) {
7623                                 TALLOC_FREE(dir_hnd);
7624                                 TALLOC_FREE(talloced);
7625                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7626                                 goto out;
7627                         }
7628
7629                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7630                                                smb_fname_dst->base_name,
7631                                                &destname)) {
7632                                 TALLOC_FREE(talloced);
7633                                 continue;
7634                         }
7635                         if (!destname) {
7636                                 TALLOC_FREE(dir_hnd);
7637                                 TALLOC_FREE(talloced);
7638                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7639                                 goto out;
7640                         }
7641
7642                         TALLOC_FREE(smb_fname_dst->base_name);
7643                         smb_fname_dst->base_name = destname;
7644
7645                         status = check_name(conn, smb_fname_src->base_name);
7646                         if (!NT_STATUS_IS_OK(status)) {
7647                                 TALLOC_FREE(dir_hnd);
7648                                 TALLOC_FREE(talloced);
7649                                 reply_nterror(req, status);
7650                                 goto out;
7651                         }
7652
7653                         status = check_name(conn, smb_fname_dst->base_name);
7654                         if (!NT_STATUS_IS_OK(status)) {
7655                                 TALLOC_FREE(dir_hnd);
7656                                 TALLOC_FREE(talloced);
7657                                 reply_nterror(req, status);
7658                                 goto out;
7659                         }
7660
7661                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7662                                 smb_fname_src->base_name,
7663                                 smb_fname_dst->base_name));
7664
7665                         status = copy_file(ctx, conn, smb_fname_src,
7666                                            smb_fname_dst, ofun, count,
7667                                            target_is_directory);
7668                         if (NT_STATUS_IS_OK(status)) {
7669                                 count++;
7670                         }
7671
7672                         TALLOC_FREE(talloced);
7673                 }
7674                 TALLOC_FREE(dir_hnd);
7675         }
7676
7677         if (count == 0) {
7678                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7679                 goto out;
7680         }
7681
7682         reply_outbuf(req, 1, 0);
7683         SSVAL(req->outbuf,smb_vwv0,count);
7684  out:
7685         TALLOC_FREE(smb_fname_src);
7686         TALLOC_FREE(smb_fname_dst);
7687         TALLOC_FREE(fname_src);
7688         TALLOC_FREE(fname_dst);
7689         TALLOC_FREE(fname_src_mask);
7690         TALLOC_FREE(fname_src_dir);
7691
7692         END_PROFILE(SMBcopy);
7693         return;
7694 }
7695
7696 #undef DBGC_CLASS
7697 #define DBGC_CLASS DBGC_LOCKING
7698
7699 /****************************************************************************
7700  Get a lock pid, dealing with large count requests.
7701 ****************************************************************************/
7702
7703 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7704                     bool large_file_format)
7705 {
7706         if(!large_file_format)
7707                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7708         else
7709                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7710 }
7711
7712 /****************************************************************************
7713  Get a lock count, dealing with large count requests.
7714 ****************************************************************************/
7715
7716 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7717                         bool large_file_format)
7718 {
7719         uint64_t count = 0;
7720
7721         if(!large_file_format) {
7722                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7723         } else {
7724                 /*
7725                  * No BVAL, this is reversed!
7726                  */
7727                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7728                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7729         }
7730
7731         return count;
7732 }
7733
7734 /****************************************************************************
7735  Get a lock offset, dealing with large offset requests.
7736 ****************************************************************************/
7737
7738 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7739                          bool large_file_format)
7740 {
7741         uint64_t offset = 0;
7742
7743         if(!large_file_format) {
7744                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7745         } else {
7746                 /*
7747                  * No BVAL, this is reversed!
7748                  */
7749                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7750                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7751         }
7752
7753         return offset;
7754 }
7755
7756 NTSTATUS smbd_do_locking(struct smb_request *req,
7757                          files_struct *fsp,
7758                          uint8_t type,
7759                          int32_t timeout,
7760                          uint16_t num_locks,
7761                          struct smbd_lock_element *locks,
7762                          bool *async)
7763 {
7764         connection_struct *conn = req->conn;
7765         int i;
7766         NTSTATUS status = NT_STATUS_OK;
7767
7768         *async = false;
7769
7770         /* Setup the timeout in seconds. */
7771
7772         if (!lp_blocking_locks(SNUM(conn))) {
7773                 timeout = 0;
7774         }
7775
7776         for(i = 0; i < (int)num_locks; i++) {
7777                 struct smbd_lock_element *e = &locks[i];
7778
7779                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7780                           "%llu, file %s timeout = %d\n",
7781                           (double)e->offset,
7782                           (double)e->count,
7783                           (unsigned long long)e->smblctx,
7784                           fsp_str_dbg(fsp),
7785                           (int)timeout));
7786
7787                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7788                         struct blocking_lock_record *blr = NULL;
7789
7790                         if (num_locks > 1) {
7791                                 /*
7792                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7793                                  * if the lock vector contains one entry. When given multiple cancel
7794                                  * requests in a single PDU we expect the server to return an
7795                                  * error. Windows servers seem to accept the request but only
7796                                  * cancel the first lock.
7797                                  * JRA - Do what Windows does (tm) :-).
7798                                  */
7799
7800 #if 0
7801                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7802                                 return NT_STATUS_DOS(ERRDOS,
7803                                                 ERRcancelviolation);
7804 #else
7805                                 /* Windows behavior. */
7806                                 if (i != 0) {
7807                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7808                                                 "cancel request\n"));
7809                                         continue;
7810                                 }
7811 #endif
7812                         }
7813
7814                         if (lp_blocking_locks(SNUM(conn))) {
7815
7816                                 /* Schedule a message to ourselves to
7817                                    remove the blocking lock record and
7818                                    return the right error. */
7819
7820                                 blr = blocking_lock_cancel_smb1(fsp,
7821                                                 e->smblctx,
7822                                                 e->offset,
7823                                                 e->count,
7824                                                 WINDOWS_LOCK,
7825                                                 type,
7826                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7827                                 if (blr == NULL) {
7828                                         return NT_STATUS_DOS(
7829                                                         ERRDOS,
7830                                                         ERRcancelviolation);
7831                                 }
7832                         }
7833                         /* Remove a matching pending lock. */
7834                         status = do_lock_cancel(fsp,
7835                                                 e->smblctx,
7836                                                 e->count,
7837                                                 e->offset,
7838                                                 WINDOWS_LOCK);
7839                 } else {
7840                         bool blocking_lock = timeout ? true : false;
7841                         bool defer_lock = false;
7842                         struct byte_range_lock *br_lck;
7843                         uint64_t block_smblctx;
7844
7845                         br_lck = do_lock(req->sconn->msg_ctx,
7846                                         fsp,
7847                                         e->smblctx,
7848                                         e->count,
7849                                         e->offset, 
7850                                         e->brltype,
7851                                         WINDOWS_LOCK,
7852                                         blocking_lock,
7853                                         &status,
7854                                         &block_smblctx);
7855
7856                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7857                                 /* Windows internal resolution for blocking locks seems
7858                                    to be about 200ms... Don't wait for less than that. JRA. */
7859                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7860                                         timeout = lp_lock_spin_time();
7861                                 }
7862                                 defer_lock = true;
7863                         }
7864
7865                         /* If a lock sent with timeout of zero would fail, and
7866                          * this lock has been requested multiple times,
7867                          * according to brl_lock_failed() we convert this
7868                          * request to a blocking lock with a timeout of between
7869                          * 150 - 300 milliseconds.
7870                          *
7871                          * If lp_lock_spin_time() has been set to 0, we skip
7872                          * this blocking retry and fail immediately.
7873                          *
7874                          * Replacement for do_lock_spin(). JRA. */
7875
7876                         if (!req->sconn->using_smb2 &&
7877                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7878                             lp_lock_spin_time() && !blocking_lock &&
7879                             NT_STATUS_EQUAL((status),
7880                                 NT_STATUS_FILE_LOCK_CONFLICT))
7881                         {
7882                                 defer_lock = true;
7883                                 timeout = lp_lock_spin_time();
7884                         }
7885
7886                         if (br_lck && defer_lock) {
7887                                 /*
7888                                  * A blocking lock was requested. Package up
7889                                  * this smb into a queued request and push it
7890                                  * onto the blocking lock queue.
7891                                  */
7892                                 if(push_blocking_lock_request(br_lck,
7893                                                         req,
7894                                                         fsp,
7895                                                         timeout,
7896                                                         i,
7897                                                         e->smblctx,
7898                                                         e->brltype,
7899                                                         WINDOWS_LOCK,
7900                                                         e->offset,
7901                                                         e->count,
7902                                                         block_smblctx)) {
7903                                         TALLOC_FREE(br_lck);
7904                                         *async = true;
7905                                         return NT_STATUS_OK;
7906                                 }
7907                         }
7908
7909                         TALLOC_FREE(br_lck);
7910                 }
7911
7912                 if (!NT_STATUS_IS_OK(status)) {
7913                         break;
7914                 }
7915         }
7916
7917         /* If any of the above locks failed, then we must unlock
7918            all of the previous locks (X/Open spec). */
7919
7920         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7921
7922                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7923                         i = -1; /* we want to skip the for loop */
7924                 }
7925
7926                 /*
7927                  * Ensure we don't do a remove on the lock that just failed,
7928                  * as under POSIX rules, if we have a lock already there, we
7929                  * will delete it (and we shouldn't) .....
7930                  */
7931                 for(i--; i >= 0; i--) {
7932                         struct smbd_lock_element *e = &locks[i];
7933
7934                         do_unlock(req->sconn->msg_ctx,
7935                                 fsp,
7936                                 e->smblctx,
7937                                 e->count,
7938                                 e->offset,
7939                                 WINDOWS_LOCK);
7940                 }
7941                 return status;
7942         }
7943
7944         DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7945                   fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7946
7947         return NT_STATUS_OK;
7948 }
7949
7950 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7951                            files_struct *fsp,
7952                            uint16_t num_ulocks,
7953                            struct smbd_lock_element *ulocks)
7954 {
7955         int i;
7956
7957         for(i = 0; i < (int)num_ulocks; i++) {
7958                 struct smbd_lock_element *e = &ulocks[i];
7959                 NTSTATUS status;
7960
7961                 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7962                           "pid %u, file %s\n", __func__,
7963                           (double)e->offset,
7964                           (double)e->count,
7965                           (unsigned int)e->smblctx,
7966                           fsp_str_dbg(fsp)));
7967
7968                 if (e->brltype != UNLOCK_LOCK) {
7969                         /* this can only happen with SMB2 */
7970                         return NT_STATUS_INVALID_PARAMETER;
7971                 }
7972
7973                 status = do_unlock(req->sconn->msg_ctx,
7974                                 fsp,
7975                                 e->smblctx,
7976                                 e->count,
7977                                 e->offset,
7978                                 WINDOWS_LOCK);
7979
7980                 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7981                            nt_errstr(status)));
7982
7983                 if (!NT_STATUS_IS_OK(status)) {
7984                         return status;
7985                 }
7986         }
7987
7988         DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7989                   num_ulocks));
7990
7991         return NT_STATUS_OK;
7992 }
7993
7994 /****************************************************************************
7995  Reply to a lockingX request.
7996 ****************************************************************************/
7997
7998 void reply_lockingX(struct smb_request *req)
7999 {
8000         connection_struct *conn = req->conn;
8001         files_struct *fsp;
8002         unsigned char locktype;
8003         unsigned char oplocklevel;
8004         uint16_t num_ulocks;
8005         uint16_t num_locks;
8006         int32_t lock_timeout;
8007         int i;
8008         const uint8_t *data;
8009         bool large_file_format;
8010         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8011         struct smbd_lock_element *ulocks;
8012         struct smbd_lock_element *locks;
8013         bool async = false;
8014
8015         START_PROFILE(SMBlockingX);
8016
8017         if (req->wct < 8) {
8018                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8019                 END_PROFILE(SMBlockingX);
8020                 return;
8021         }
8022
8023         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8024         locktype = CVAL(req->vwv+3, 0);
8025         oplocklevel = CVAL(req->vwv+3, 1);
8026         num_ulocks = SVAL(req->vwv+6, 0);
8027         num_locks = SVAL(req->vwv+7, 0);
8028         lock_timeout = IVAL(req->vwv+4, 0);
8029         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8030
8031         if (!check_fsp(conn, req, fsp)) {
8032                 END_PROFILE(SMBlockingX);
8033                 return;
8034         }
8035
8036         data = req->buf;
8037
8038         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8039                 /* we don't support these - and CANCEL_LOCK makes w2k
8040                    and XP reboot so I don't really want to be
8041                    compatible! (tridge) */
8042                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8043                 END_PROFILE(SMBlockingX);
8044                 return;
8045         }
8046
8047         /* Check if this is an oplock break on a file
8048            we have granted an oplock on.
8049         */
8050         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8051                 /* Client can insist on breaking to none. */
8052                 bool break_to_none = (oplocklevel == 0);
8053                 bool result;
8054
8055                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8056                          "for %s\n", (unsigned int)oplocklevel,
8057                          fsp_fnum_dbg(fsp)));
8058
8059                 /*
8060                  * Make sure we have granted an exclusive or batch oplock on
8061                  * this file.
8062                  */
8063
8064                 if (fsp->oplock_type == 0) {
8065
8066                         /* The Samba4 nbench simulator doesn't understand
8067                            the difference between break to level2 and break
8068                            to none from level2 - it sends oplock break
8069                            replies in both cases. Don't keep logging an error
8070                            message here - just ignore it. JRA. */
8071
8072                         DEBUG(5,("reply_lockingX: Error : oplock break from "
8073                                  "client for %s (oplock=%d) and no "
8074                                  "oplock granted on this file (%s).\n",
8075                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
8076                                  fsp_str_dbg(fsp)));
8077
8078                         /* if this is a pure oplock break request then don't
8079                          * send a reply */
8080                         if (num_locks == 0 && num_ulocks == 0) {
8081                                 END_PROFILE(SMBlockingX);
8082                                 return;
8083                         } else {
8084                                 END_PROFILE(SMBlockingX);
8085                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8086                                 return;
8087                         }
8088                 }
8089
8090                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8091                     (break_to_none)) {
8092                         result = remove_oplock(fsp);
8093                 } else {
8094                         result = downgrade_oplock(fsp);
8095                 }
8096
8097                 if (!result) {
8098                         DEBUG(0, ("reply_lockingX: error in removing "
8099                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
8100                         /* Hmmm. Is this panic justified? */
8101                         smb_panic("internal tdb error");
8102                 }
8103
8104                 /* if this is a pure oplock break request then don't send a
8105                  * reply */
8106                 if (num_locks == 0 && num_ulocks == 0) {
8107                         /* Sanity check - ensure a pure oplock break is not a
8108                            chained request. */
8109                         if (CVAL(req->vwv+0, 0) != 0xff) {
8110                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
8111                                          "break is a chained %d request !\n",
8112                                          (unsigned int)CVAL(req->vwv+0, 0)));
8113                         }
8114                         END_PROFILE(SMBlockingX);
8115                         return;
8116                 }
8117         }
8118
8119         if (req->buflen <
8120             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8121                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8122                 END_PROFILE(SMBlockingX);
8123                 return;
8124         }
8125
8126         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8127         if (ulocks == NULL) {
8128                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8129                 END_PROFILE(SMBlockingX);
8130                 return;
8131         }
8132
8133         locks = talloc_array(req, struct smbd_lock_element, num_locks);
8134         if (locks == NULL) {
8135                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8136                 END_PROFILE(SMBlockingX);
8137                 return;
8138         }
8139
8140         /* Data now points at the beginning of the list
8141            of smb_unlkrng structs */
8142         for(i = 0; i < (int)num_ulocks; i++) {
8143                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8144                 ulocks[i].count = get_lock_count(data, i, large_file_format);
8145                 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8146                 ulocks[i].brltype = UNLOCK_LOCK;
8147         }
8148
8149         /* Now do any requested locks */
8150         data += ((large_file_format ? 20 : 10)*num_ulocks);
8151
8152         /* Data now points at the beginning of the list
8153            of smb_lkrng structs */
8154
8155         for(i = 0; i < (int)num_locks; i++) {
8156                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8157                 locks[i].count = get_lock_count(data, i, large_file_format);
8158                 locks[i].offset = get_lock_offset(data, i, large_file_format);
8159
8160                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8161                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8162                                 locks[i].brltype = PENDING_READ_LOCK;
8163                         } else {
8164                                 locks[i].brltype = READ_LOCK;
8165                         }
8166                 } else {
8167                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8168                                 locks[i].brltype = PENDING_WRITE_LOCK;
8169                         } else {
8170                                 locks[i].brltype = WRITE_LOCK;
8171                         }
8172                 }
8173         }
8174
8175         status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8176         if (!NT_STATUS_IS_OK(status)) {
8177                 END_PROFILE(SMBlockingX);
8178                 reply_nterror(req, status);
8179                 return;
8180         }
8181
8182         status = smbd_do_locking(req, fsp,
8183                                  locktype, lock_timeout,
8184                                  num_locks, locks,
8185                                  &async);
8186         if (!NT_STATUS_IS_OK(status)) {
8187                 END_PROFILE(SMBlockingX);
8188                 reply_nterror(req, status);
8189                 return;
8190         }
8191         if (async) {
8192                 END_PROFILE(SMBlockingX);
8193                 return;
8194         }
8195
8196         reply_outbuf(req, 2, 0);
8197         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8198         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
8199
8200         DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8201                   fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8202
8203         END_PROFILE(SMBlockingX);
8204 }
8205
8206 #undef DBGC_CLASS
8207 #define DBGC_CLASS DBGC_ALL
8208
8209 /****************************************************************************
8210  Reply to a SMBreadbmpx (read block multiplex) request.
8211  Always reply with an error, if someone has a platform really needs this,
8212  please contact vl@samba.org
8213 ****************************************************************************/
8214
8215 void reply_readbmpx(struct smb_request *req)
8216 {
8217         START_PROFILE(SMBreadBmpx);
8218         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8219         END_PROFILE(SMBreadBmpx);
8220         return;
8221 }
8222
8223 /****************************************************************************
8224  Reply to a SMBreadbs (read block multiplex secondary) request.
8225  Always reply with an error, if someone has a platform really needs this,
8226  please contact vl@samba.org
8227 ****************************************************************************/
8228
8229 void reply_readbs(struct smb_request *req)
8230 {
8231         START_PROFILE(SMBreadBs);
8232         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8233         END_PROFILE(SMBreadBs);
8234         return;
8235 }
8236
8237 /****************************************************************************
8238  Reply to a SMBsetattrE.
8239 ****************************************************************************/
8240
8241 void reply_setattrE(struct smb_request *req)
8242 {
8243         connection_struct *conn = req->conn;
8244         struct smb_file_time ft;
8245         files_struct *fsp;
8246         NTSTATUS status;
8247
8248         START_PROFILE(SMBsetattrE);
8249         ZERO_STRUCT(ft);
8250
8251         if (req->wct < 7) {
8252                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8253                 goto out;
8254         }
8255
8256         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8257
8258         if(!fsp || (fsp->conn != conn)) {
8259                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8260                 goto out;
8261         }
8262
8263         /*
8264          * Convert the DOS times into unix times.
8265          */
8266
8267         ft.atime = convert_time_t_to_timespec(
8268             srv_make_unix_date2(req->vwv+3));
8269         ft.mtime = convert_time_t_to_timespec(
8270             srv_make_unix_date2(req->vwv+5));
8271         ft.create_time = convert_time_t_to_timespec(
8272             srv_make_unix_date2(req->vwv+1));
8273
8274         reply_outbuf(req, 0, 0);
8275
8276         /* 
8277          * Patch from Ray Frush <frush@engr.colostate.edu>
8278          * Sometimes times are sent as zero - ignore them.
8279          */
8280
8281         /* Ensure we have a valid stat struct for the source. */
8282         status = vfs_stat_fsp(fsp);
8283         if (!NT_STATUS_IS_OK(status)) {
8284                 reply_nterror(req, status);
8285                 goto out;
8286         }
8287
8288         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8289                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8290                 goto out;
8291         }
8292
8293         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8294         if (!NT_STATUS_IS_OK(status)) {
8295                 reply_nterror(req, status);
8296                 goto out;
8297         }
8298
8299         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8300                " createtime=%u\n",
8301                 fsp_fnum_dbg(fsp),
8302                 (unsigned int)ft.atime.tv_sec,
8303                 (unsigned int)ft.mtime.tv_sec,
8304                 (unsigned int)ft.create_time.tv_sec
8305                 ));
8306  out:
8307         END_PROFILE(SMBsetattrE);
8308         return;
8309 }
8310
8311
8312 /* Back from the dead for OS/2..... JRA. */
8313
8314 /****************************************************************************
8315  Reply to a SMBwritebmpx (write block multiplex primary) request.
8316  Always reply with an error, if someone has a platform really needs this,
8317  please contact vl@samba.org
8318 ****************************************************************************/
8319
8320 void reply_writebmpx(struct smb_request *req)
8321 {
8322         START_PROFILE(SMBwriteBmpx);
8323         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8324         END_PROFILE(SMBwriteBmpx);
8325         return;
8326 }
8327
8328 /****************************************************************************
8329  Reply to a SMBwritebs (write block multiplex secondary) request.
8330  Always reply with an error, if someone has a platform really needs this,
8331  please contact vl@samba.org
8332 ****************************************************************************/
8333
8334 void reply_writebs(struct smb_request *req)
8335 {
8336         START_PROFILE(SMBwriteBs);
8337         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8338         END_PROFILE(SMBwriteBs);
8339         return;
8340 }
8341
8342 /****************************************************************************
8343  Reply to a SMBgetattrE.
8344 ****************************************************************************/
8345
8346 void reply_getattrE(struct smb_request *req)
8347 {
8348         connection_struct *conn = req->conn;
8349         int mode;
8350         files_struct *fsp;
8351         struct timespec create_ts;
8352
8353         START_PROFILE(SMBgetattrE);
8354
8355         if (req->wct < 1) {
8356                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357                 END_PROFILE(SMBgetattrE);
8358                 return;
8359         }
8360
8361         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8362
8363         if(!fsp || (fsp->conn != conn)) {
8364                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8365                 END_PROFILE(SMBgetattrE);
8366                 return;
8367         }
8368
8369         /* Do an fstat on this file */
8370         if(fsp_stat(fsp)) {
8371                 reply_nterror(req, map_nt_error_from_unix(errno));
8372                 END_PROFILE(SMBgetattrE);
8373                 return;
8374         }
8375
8376         mode = dos_mode(conn, fsp->fsp_name);
8377
8378         /*
8379          * Convert the times into dos times. Set create
8380          * date to be last modify date as UNIX doesn't save
8381          * this.
8382          */
8383
8384         reply_outbuf(req, 11, 0);
8385
8386         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8387         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8388         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8389                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8390         /* Should we check pending modtime here ? JRA */
8391         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8392                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8393
8394         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8395                 SIVAL(req->outbuf, smb_vwv6, 0);
8396                 SIVAL(req->outbuf, smb_vwv8, 0);
8397         } else {
8398                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8399                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8400                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8401         }
8402         SSVAL(req->outbuf,smb_vwv10, mode);
8403
8404         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8405
8406         END_PROFILE(SMBgetattrE);
8407         return;
8408 }