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