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