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