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