Fix bug #8664 - Renaming a symlink fails if the symlink target is outside of the...
[mat/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         if (nwritten < (ssize_t)numtowrite) {
4675                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4676                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4677         }
4678
4679         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4680                 fsp->fnum, (int)numtowrite, (int)nwritten));
4681
4682         status = sync_file(conn, fsp, write_through);
4683         if (!NT_STATUS_IS_OK(status)) {
4684                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4685                          fsp_str_dbg(fsp), nt_errstr(status)));
4686                 reply_nterror(req, status);
4687                 goto out;
4688         }
4689
4690         END_PROFILE(SMBwriteX);
4691         chain_reply(req);
4692         return;
4693
4694 out:
4695         END_PROFILE(SMBwriteX);
4696         return;
4697 }
4698
4699 /****************************************************************************
4700  Reply to a lseek.
4701 ****************************************************************************/
4702
4703 void reply_lseek(struct smb_request *req)
4704 {
4705         connection_struct *conn = req->conn;
4706         SMB_OFF_T startpos;
4707         SMB_OFF_T res= -1;
4708         int mode,umode;
4709         files_struct *fsp;
4710
4711         START_PROFILE(SMBlseek);
4712
4713         if (req->wct < 4) {
4714                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4715                 END_PROFILE(SMBlseek);
4716                 return;
4717         }
4718
4719         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4720
4721         if (!check_fsp(conn, req, fsp)) {
4722                 return;
4723         }
4724
4725         flush_write_cache(fsp, SEEK_FLUSH);
4726
4727         mode = SVAL(req->vwv+1, 0) & 3;
4728         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4729         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4730
4731         switch (mode) {
4732                 case 0:
4733                         umode = SEEK_SET;
4734                         res = startpos;
4735                         break;
4736                 case 1:
4737                         umode = SEEK_CUR;
4738                         res = fsp->fh->pos + startpos;
4739                         break;
4740                 case 2:
4741                         umode = SEEK_END;
4742                         break;
4743                 default:
4744                         umode = SEEK_SET;
4745                         res = startpos;
4746                         break;
4747         }
4748
4749         if (umode == SEEK_END) {
4750                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4751                         if(errno == EINVAL) {
4752                                 SMB_OFF_T current_pos = startpos;
4753
4754                                 if(fsp_stat(fsp) == -1) {
4755                                         reply_nterror(req,
4756                                                 map_nt_error_from_unix(errno));
4757                                         END_PROFILE(SMBlseek);
4758                                         return;
4759                                 }
4760
4761                                 current_pos += fsp->fsp_name->st.st_ex_size;
4762                                 if(current_pos < 0)
4763                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4764                         }
4765                 }
4766
4767                 if(res == -1) {
4768                         reply_nterror(req, map_nt_error_from_unix(errno));
4769                         END_PROFILE(SMBlseek);
4770                         return;
4771                 }
4772         }
4773
4774         fsp->fh->pos = res;
4775
4776         reply_outbuf(req, 2, 0);
4777         SIVAL(req->outbuf,smb_vwv0,res);
4778
4779         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4780                 fsp->fnum, (double)startpos, (double)res, mode));
4781
4782         END_PROFILE(SMBlseek);
4783         return;
4784 }
4785
4786 /****************************************************************************
4787  Reply to a flush.
4788 ****************************************************************************/
4789
4790 void reply_flush(struct smb_request *req)
4791 {
4792         connection_struct *conn = req->conn;
4793         uint16 fnum;
4794         files_struct *fsp;
4795
4796         START_PROFILE(SMBflush);
4797
4798         if (req->wct < 1) {
4799                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4800                 return;
4801         }
4802
4803         fnum = SVAL(req->vwv+0, 0);
4804         fsp = file_fsp(req, fnum);
4805
4806         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4807                 return;
4808         }
4809
4810         if (!fsp) {
4811                 file_sync_all(conn);
4812         } else {
4813                 NTSTATUS status = sync_file(conn, fsp, True);
4814                 if (!NT_STATUS_IS_OK(status)) {
4815                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4816                                 fsp_str_dbg(fsp), nt_errstr(status)));
4817                         reply_nterror(req, status);
4818                         END_PROFILE(SMBflush);
4819                         return;
4820                 }
4821         }
4822
4823         reply_outbuf(req, 0, 0);
4824
4825         DEBUG(3,("flush\n"));
4826         END_PROFILE(SMBflush);
4827         return;
4828 }
4829
4830 /****************************************************************************
4831  Reply to a exit.
4832  conn POINTER CAN BE NULL HERE !
4833 ****************************************************************************/
4834
4835 void reply_exit(struct smb_request *req)
4836 {
4837         START_PROFILE(SMBexit);
4838
4839         file_close_pid(req->sconn, req->smbpid, req->vuid);
4840
4841         reply_outbuf(req, 0, 0);
4842
4843         DEBUG(3,("exit\n"));
4844
4845         END_PROFILE(SMBexit);
4846         return;
4847 }
4848
4849 /****************************************************************************
4850  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4851 ****************************************************************************/
4852
4853 void reply_close(struct smb_request *req)
4854 {
4855         connection_struct *conn = req->conn;
4856         NTSTATUS status = NT_STATUS_OK;
4857         files_struct *fsp = NULL;
4858         START_PROFILE(SMBclose);
4859
4860         if (req->wct < 3) {
4861                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4862                 END_PROFILE(SMBclose);
4863                 return;
4864         }
4865
4866         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4867
4868         /*
4869          * We can only use check_fsp if we know it's not a directory.
4870          */
4871
4872         if (!check_fsp_open(conn, req, fsp)) {
4873                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4874                 END_PROFILE(SMBclose);
4875                 return;
4876         }
4877
4878         if(fsp->is_directory) {
4879                 /*
4880                  * Special case - close NT SMB directory handle.
4881                  */
4882                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4883                 status = close_file(req, fsp, NORMAL_CLOSE);
4884         } else {
4885                 time_t t;
4886                 /*
4887                  * Close ordinary file.
4888                  */
4889
4890                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4891                          fsp->fh->fd, fsp->fnum,
4892                          conn->num_files_open));
4893
4894                 /*
4895                  * Take care of any time sent in the close.
4896                  */
4897
4898                 t = srv_make_unix_date3(req->vwv+1);
4899                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4900
4901                 /*
4902                  * close_file() returns the unix errno if an error
4903                  * was detected on close - normally this is due to
4904                  * a disk full error. If not then it was probably an I/O error.
4905                  */
4906
4907                 status = close_file(req, fsp, NORMAL_CLOSE);
4908         }  
4909
4910         if (!NT_STATUS_IS_OK(status)) {
4911                 reply_nterror(req, status);
4912                 END_PROFILE(SMBclose);
4913                 return;
4914         }
4915
4916         reply_outbuf(req, 0, 0);
4917         END_PROFILE(SMBclose);
4918         return;
4919 }
4920
4921 /****************************************************************************
4922  Reply to a writeclose (Core+ protocol).
4923 ****************************************************************************/
4924
4925 void reply_writeclose(struct smb_request *req)
4926 {
4927         connection_struct *conn = req->conn;
4928         size_t numtowrite;
4929         ssize_t nwritten = -1;
4930         NTSTATUS close_status = NT_STATUS_OK;
4931         SMB_OFF_T startpos;
4932         const char *data;
4933         struct timespec mtime;
4934         files_struct *fsp;
4935         struct lock_struct lock;
4936
4937         START_PROFILE(SMBwriteclose);
4938
4939         if (req->wct < 6) {
4940                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4941                 END_PROFILE(SMBwriteclose);
4942                 return;
4943         }
4944
4945         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4946
4947         if (!check_fsp(conn, req, fsp)) {
4948                 END_PROFILE(SMBwriteclose);
4949                 return;
4950         }
4951         if (!CHECK_WRITE(fsp)) {
4952                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4953                 END_PROFILE(SMBwriteclose);
4954                 return;
4955         }
4956
4957         numtowrite = SVAL(req->vwv+1, 0);
4958         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4959         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4960         data = (const char *)req->buf + 1;
4961
4962         if (!fsp->print_file) {
4963                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4964                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4965                     &lock);
4966
4967                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4968                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4969                         END_PROFILE(SMBwriteclose);
4970                         return;
4971                 }
4972         }
4973
4974         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4975
4976         set_close_write_time(fsp, mtime);
4977
4978         /*
4979          * More insanity. W2K only closes the file if writelen > 0.
4980          * JRA.
4981          */
4982
4983         if (numtowrite) {
4984                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4985                          "file %s\n", fsp_str_dbg(fsp)));
4986                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4987         }
4988
4989         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4990                  fsp->fnum, (int)numtowrite, (int)nwritten,
4991                  conn->num_files_open));
4992
4993         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4994                 reply_nterror(req, NT_STATUS_DISK_FULL);
4995                 goto strict_unlock;
4996         }
4997
4998         if(!NT_STATUS_IS_OK(close_status)) {
4999                 reply_nterror(req, close_status);
5000                 goto strict_unlock;
5001         }
5002
5003         reply_outbuf(req, 1, 0);
5004
5005         SSVAL(req->outbuf,smb_vwv0,nwritten);
5006
5007 strict_unlock:
5008         if (numtowrite && !fsp->print_file) {
5009                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5010         }
5011
5012         END_PROFILE(SMBwriteclose);
5013         return;
5014 }
5015
5016 #undef DBGC_CLASS
5017 #define DBGC_CLASS DBGC_LOCKING
5018
5019 /****************************************************************************
5020  Reply to a lock.
5021 ****************************************************************************/
5022
5023 void reply_lock(struct smb_request *req)
5024 {
5025         connection_struct *conn = req->conn;
5026         uint64_t count,offset;
5027         NTSTATUS status;
5028         files_struct *fsp;
5029         struct byte_range_lock *br_lck = NULL;
5030
5031         START_PROFILE(SMBlock);
5032
5033         if (req->wct < 5) {
5034                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035                 END_PROFILE(SMBlock);
5036                 return;
5037         }
5038
5039         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5040
5041         if (!check_fsp(conn, req, fsp)) {
5042                 END_PROFILE(SMBlock);
5043                 return;
5044         }
5045
5046         count = (uint64_t)IVAL(req->vwv+1, 0);
5047         offset = (uint64_t)IVAL(req->vwv+3, 0);
5048
5049         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5050                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5051
5052         br_lck = do_lock(req->sconn->msg_ctx,
5053                         fsp,
5054                         (uint64_t)req->smbpid,
5055                         count,
5056                         offset,
5057                         WRITE_LOCK,
5058                         WINDOWS_LOCK,
5059                         False, /* Non-blocking lock. */
5060                         &status,
5061                         NULL,
5062                         NULL);
5063
5064         TALLOC_FREE(br_lck);
5065
5066         if (NT_STATUS_V(status)) {
5067                 reply_nterror(req, status);
5068                 END_PROFILE(SMBlock);
5069                 return;
5070         }
5071
5072         reply_outbuf(req, 0, 0);
5073
5074         END_PROFILE(SMBlock);
5075         return;
5076 }
5077
5078 /****************************************************************************
5079  Reply to a unlock.
5080 ****************************************************************************/
5081
5082 void reply_unlock(struct smb_request *req)
5083 {
5084         connection_struct *conn = req->conn;
5085         uint64_t count,offset;
5086         NTSTATUS status;
5087         files_struct *fsp;
5088
5089         START_PROFILE(SMBunlock);
5090
5091         if (req->wct < 5) {
5092                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5093                 END_PROFILE(SMBunlock);
5094                 return;
5095         }
5096
5097         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5098
5099         if (!check_fsp(conn, req, fsp)) {
5100                 END_PROFILE(SMBunlock);
5101                 return;
5102         }
5103
5104         count = (uint64_t)IVAL(req->vwv+1, 0);
5105         offset = (uint64_t)IVAL(req->vwv+3, 0);
5106
5107         status = do_unlock(req->sconn->msg_ctx,
5108                         fsp,
5109                         (uint64_t)req->smbpid,
5110                         count,
5111                         offset,
5112                         WINDOWS_LOCK);
5113
5114         if (NT_STATUS_V(status)) {
5115                 reply_nterror(req, status);
5116                 END_PROFILE(SMBunlock);
5117                 return;
5118         }
5119
5120         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5121                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5122
5123         reply_outbuf(req, 0, 0);
5124
5125         END_PROFILE(SMBunlock);
5126         return;
5127 }
5128
5129 #undef DBGC_CLASS
5130 #define DBGC_CLASS DBGC_ALL
5131
5132 /****************************************************************************
5133  Reply to a tdis.
5134  conn POINTER CAN BE NULL HERE !
5135 ****************************************************************************/
5136
5137 void reply_tdis(struct smb_request *req)
5138 {
5139         connection_struct *conn = req->conn;
5140         START_PROFILE(SMBtdis);
5141
5142         if (!conn) {
5143                 DEBUG(4,("Invalid connection in tdis\n"));
5144                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5145                 END_PROFILE(SMBtdis);
5146                 return;
5147         }
5148
5149         conn->used = False;
5150
5151         close_cnum(conn,req->vuid);
5152         req->conn = NULL;
5153
5154         reply_outbuf(req, 0, 0);
5155         END_PROFILE(SMBtdis);
5156         return;
5157 }
5158
5159 /****************************************************************************
5160  Reply to a echo.
5161  conn POINTER CAN BE NULL HERE !
5162 ****************************************************************************/
5163
5164 void reply_echo(struct smb_request *req)
5165 {
5166         connection_struct *conn = req->conn;
5167         struct smb_perfcount_data local_pcd;
5168         struct smb_perfcount_data *cur_pcd;
5169         int smb_reverb;
5170         int seq_num;
5171
5172         START_PROFILE(SMBecho);
5173
5174         smb_init_perfcount_data(&local_pcd);
5175
5176         if (req->wct < 1) {
5177                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5178                 END_PROFILE(SMBecho);
5179                 return;
5180         }
5181
5182         smb_reverb = SVAL(req->vwv+0, 0);
5183
5184         reply_outbuf(req, 1, req->buflen);
5185
5186         /* copy any incoming data back out */
5187         if (req->buflen > 0) {
5188                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5189         }
5190
5191         if (smb_reverb > 100) {
5192                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5193                 smb_reverb = 100;
5194         }
5195
5196         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5197
5198                 /* this makes sure we catch the request pcd */
5199                 if (seq_num == smb_reverb) {
5200                         cur_pcd = &req->pcd;
5201                 } else {
5202                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5203                         cur_pcd = &local_pcd;
5204                 }
5205
5206                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5207
5208                 show_msg((char *)req->outbuf);
5209                 if (!srv_send_smb(req->sconn,
5210                                 (char *)req->outbuf,
5211                                 true, req->seqnum+1,
5212                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5213                                 cur_pcd))
5214                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5215         }
5216
5217         DEBUG(3,("echo %d times\n", smb_reverb));
5218
5219         TALLOC_FREE(req->outbuf);
5220
5221         END_PROFILE(SMBecho);
5222         return;
5223 }
5224
5225 /****************************************************************************
5226  Reply to a printopen.
5227 ****************************************************************************/
5228
5229 void reply_printopen(struct smb_request *req)
5230 {
5231         connection_struct *conn = req->conn;
5232         files_struct *fsp;
5233         NTSTATUS status;
5234
5235         START_PROFILE(SMBsplopen);
5236
5237         if (req->wct < 2) {
5238                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239                 END_PROFILE(SMBsplopen);
5240                 return;
5241         }
5242
5243         if (!CAN_PRINT(conn)) {
5244                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5245                 END_PROFILE(SMBsplopen);
5246                 return;
5247         }
5248
5249         status = file_new(req, conn, &fsp);
5250         if(!NT_STATUS_IS_OK(status)) {
5251                 reply_nterror(req, status);
5252                 END_PROFILE(SMBsplopen);
5253                 return;
5254         }
5255
5256         /* Open for exclusive use, write only. */
5257         status = print_spool_open(fsp, NULL, req->vuid);
5258
5259         if (!NT_STATUS_IS_OK(status)) {
5260                 file_free(req, fsp);
5261                 reply_nterror(req, status);
5262                 END_PROFILE(SMBsplopen);
5263                 return;
5264         }
5265
5266         reply_outbuf(req, 1, 0);
5267         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5268
5269         DEBUG(3,("openprint fd=%d fnum=%d\n",
5270                  fsp->fh->fd, fsp->fnum));
5271
5272         END_PROFILE(SMBsplopen);
5273         return;
5274 }
5275
5276 /****************************************************************************
5277  Reply to a printclose.
5278 ****************************************************************************/
5279
5280 void reply_printclose(struct smb_request *req)
5281 {
5282         connection_struct *conn = req->conn;
5283         files_struct *fsp;
5284         NTSTATUS status;
5285
5286         START_PROFILE(SMBsplclose);
5287
5288         if (req->wct < 1) {
5289                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5290                 END_PROFILE(SMBsplclose);
5291                 return;
5292         }
5293
5294         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5295
5296         if (!check_fsp(conn, req, fsp)) {
5297                 END_PROFILE(SMBsplclose);
5298                 return;
5299         }
5300
5301         if (!CAN_PRINT(conn)) {
5302                 reply_force_doserror(req, ERRSRV, ERRerror);
5303                 END_PROFILE(SMBsplclose);
5304                 return;
5305         }
5306
5307         DEBUG(3,("printclose fd=%d fnum=%d\n",
5308                  fsp->fh->fd,fsp->fnum));
5309
5310         status = close_file(req, fsp, NORMAL_CLOSE);
5311
5312         if(!NT_STATUS_IS_OK(status)) {
5313                 reply_nterror(req, status);
5314                 END_PROFILE(SMBsplclose);
5315                 return;
5316         }
5317
5318         reply_outbuf(req, 0, 0);
5319
5320         END_PROFILE(SMBsplclose);
5321         return;
5322 }
5323
5324 /****************************************************************************
5325  Reply to a printqueue.
5326 ****************************************************************************/
5327
5328 void reply_printqueue(struct smb_request *req)
5329 {
5330         connection_struct *conn = req->conn;
5331         int max_count;
5332         int start_index;
5333
5334         START_PROFILE(SMBsplretq);
5335
5336         if (req->wct < 2) {
5337                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5338                 END_PROFILE(SMBsplretq);
5339                 return;
5340         }
5341
5342         max_count = SVAL(req->vwv+0, 0);
5343         start_index = SVAL(req->vwv+1, 0);
5344
5345         /* we used to allow the client to get the cnum wrong, but that
5346            is really quite gross and only worked when there was only
5347            one printer - I think we should now only accept it if they
5348            get it right (tridge) */
5349         if (!CAN_PRINT(conn)) {
5350                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5351                 END_PROFILE(SMBsplretq);
5352                 return;
5353         }
5354
5355         reply_outbuf(req, 2, 3);
5356         SSVAL(req->outbuf,smb_vwv0,0);
5357         SSVAL(req->outbuf,smb_vwv1,0);
5358         SCVAL(smb_buf(req->outbuf),0,1);
5359         SSVAL(smb_buf(req->outbuf),1,0);
5360
5361         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5362                  start_index, max_count));
5363
5364         {
5365                 TALLOC_CTX *mem_ctx = talloc_tos();
5366                 NTSTATUS status;
5367                 WERROR werr;
5368                 const char *sharename = lp_servicename(SNUM(conn));
5369                 struct rpc_pipe_client *cli = NULL;
5370                 struct dcerpc_binding_handle *b = NULL;
5371                 struct policy_handle handle;
5372                 struct spoolss_DevmodeContainer devmode_ctr;
5373                 union spoolss_JobInfo *info;
5374                 uint32_t count;
5375                 uint32_t num_to_get;
5376                 uint32_t first;
5377                 uint32_t i;
5378
5379                 ZERO_STRUCT(handle);
5380
5381                 status = rpc_pipe_open_interface(conn,
5382                                                  &ndr_table_spoolss.syntax_id,
5383                                                  conn->session_info,
5384                                                  conn->sconn->remote_address,
5385                                                  conn->sconn->msg_ctx,
5386                                                  &cli);
5387                 if (!NT_STATUS_IS_OK(status)) {
5388                         DEBUG(0, ("reply_printqueue: "
5389                                   "could not connect to spoolss: %s\n",
5390                                   nt_errstr(status)));
5391                         reply_nterror(req, status);
5392                         goto out;
5393                 }
5394                 b = cli->binding_handle;
5395
5396                 ZERO_STRUCT(devmode_ctr);
5397
5398                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5399                                                 sharename,
5400                                                 NULL, devmode_ctr,
5401                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5402                                                 &handle,
5403                                                 &werr);
5404                 if (!NT_STATUS_IS_OK(status)) {
5405                         reply_nterror(req, status);
5406                         goto out;
5407                 }
5408                 if (!W_ERROR_IS_OK(werr)) {
5409                         reply_nterror(req, werror_to_ntstatus(werr));
5410                         goto out;
5411                 }
5412
5413                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5414                                                &handle,
5415                                                0, /* firstjob */
5416                                                0xff, /* numjobs */
5417                                                2, /* level */
5418                                                0, /* offered */
5419                                                &count,
5420                                                &info);
5421                 if (!W_ERROR_IS_OK(werr)) {
5422                         reply_nterror(req, werror_to_ntstatus(werr));
5423                         goto out;
5424                 }
5425
5426                 if (max_count > 0) {
5427                         first = start_index;
5428                 } else {
5429                         first = start_index + max_count + 1;
5430                 }
5431
5432                 if (first >= count) {
5433                         num_to_get = first;
5434                 } else {
5435                         num_to_get = first + MIN(ABS(max_count), count - first);
5436                 }
5437
5438                 for (i = first; i < num_to_get; i++) {
5439                         char blob[28];
5440                         char *p = blob;
5441                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5442                         int qstatus;
5443                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5444                                                         info[i].info2.job_id);
5445
5446                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5447                                 qstatus = 2;
5448                         } else {
5449                                 qstatus = 3;
5450                         }
5451
5452                         srv_put_dos_date2(p, 0, qtime);
5453                         SCVAL(p, 4, qstatus);
5454                         SSVAL(p, 5, qrapjobid);
5455                         SIVAL(p, 7, info[i].info2.size);
5456                         SCVAL(p, 11, 0);
5457                         srvstr_push(blob, req->flags2, p+12,
5458                                     info[i].info2.notify_name, 16, STR_ASCII);
5459
5460                         if (message_push_blob(
5461                                     &req->outbuf,
5462                                     data_blob_const(
5463                                             blob, sizeof(blob))) == -1) {
5464                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5465                                 goto out;
5466                         }
5467                 }
5468
5469                 if (count > 0) {
5470                         SSVAL(req->outbuf,smb_vwv0,count);
5471                         SSVAL(req->outbuf,smb_vwv1,
5472                               (max_count>0?first+count:first-1));
5473                         SCVAL(smb_buf(req->outbuf),0,1);
5474                         SSVAL(smb_buf(req->outbuf),1,28*count);
5475                 }
5476
5477
5478                 DEBUG(3, ("%u entries returned in queue\n",
5479                           (unsigned)count));
5480
5481 out:
5482                 if (b && is_valid_policy_hnd(&handle)) {
5483                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5484                 }
5485
5486         }
5487
5488         END_PROFILE(SMBsplretq);
5489         return;
5490 }
5491
5492 /****************************************************************************
5493  Reply to a printwrite.
5494 ****************************************************************************/
5495
5496 void reply_printwrite(struct smb_request *req)
5497 {
5498         connection_struct *conn = req->conn;
5499         int numtowrite;
5500         const char *data;
5501         files_struct *fsp;
5502
5503         START_PROFILE(SMBsplwr);
5504
5505         if (req->wct < 1) {
5506                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5507                 END_PROFILE(SMBsplwr);
5508                 return;
5509         }
5510
5511         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5512
5513         if (!check_fsp(conn, req, fsp)) {
5514                 END_PROFILE(SMBsplwr);
5515                 return;
5516         }
5517
5518         if (!fsp->print_file) {
5519                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5520                 END_PROFILE(SMBsplwr);
5521                 return;
5522         }
5523
5524         if (!CHECK_WRITE(fsp)) {
5525                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5526                 END_PROFILE(SMBsplwr);
5527                 return;
5528         }
5529
5530         numtowrite = SVAL(req->buf, 1);
5531
5532         if (req->buflen < numtowrite + 3) {
5533                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5534                 END_PROFILE(SMBsplwr);
5535                 return;
5536         }
5537
5538         data = (const char *)req->buf + 3;
5539
5540         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5541                 reply_nterror(req, map_nt_error_from_unix(errno));
5542                 END_PROFILE(SMBsplwr);
5543                 return;
5544         }
5545
5546         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5547
5548         END_PROFILE(SMBsplwr);
5549         return;
5550 }
5551
5552 /****************************************************************************
5553  Reply to a mkdir.
5554 ****************************************************************************/
5555
5556 void reply_mkdir(struct smb_request *req)
5557 {
5558         connection_struct *conn = req->conn;
5559         struct smb_filename *smb_dname = NULL;
5560         char *directory = NULL;
5561         NTSTATUS status;
5562         TALLOC_CTX *ctx = talloc_tos();
5563
5564         START_PROFILE(SMBmkdir);
5565
5566         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5567                             STR_TERMINATE, &status);
5568         if (!NT_STATUS_IS_OK(status)) {
5569                 reply_nterror(req, status);
5570                 goto out;
5571         }
5572
5573         status = filename_convert(ctx, conn,
5574                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5575                                  directory,
5576                                  0,
5577                                  NULL,
5578                                  &smb_dname);
5579         if (!NT_STATUS_IS_OK(status)) {
5580                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5581                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5582                                         ERRSRV, ERRbadpath);
5583                         goto out;
5584                 }
5585                 reply_nterror(req, status);
5586                 goto out;
5587         }
5588
5589         status = create_directory(conn, req, smb_dname);
5590
5591         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5592
5593         if (!NT_STATUS_IS_OK(status)) {
5594
5595                 if (!use_nt_status()
5596                     && NT_STATUS_EQUAL(status,
5597                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5598                         /*
5599                          * Yes, in the DOS error code case we get a
5600                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5601                          * samba4 torture test.
5602                          */
5603                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5604                 }
5605
5606                 reply_nterror(req, status);
5607                 goto out;
5608         }
5609
5610         reply_outbuf(req, 0, 0);
5611
5612         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5613  out:
5614         TALLOC_FREE(smb_dname);
5615         END_PROFILE(SMBmkdir);
5616         return;
5617 }
5618
5619 /****************************************************************************
5620  Reply to a rmdir.
5621 ****************************************************************************/
5622
5623 void reply_rmdir(struct smb_request *req)
5624 {
5625         connection_struct *conn = req->conn;
5626         struct smb_filename *smb_dname = NULL;
5627         char *directory = NULL;
5628         NTSTATUS status;
5629         TALLOC_CTX *ctx = talloc_tos();
5630         files_struct *fsp = NULL;
5631         int info = 0;
5632         struct smbd_server_connection *sconn = req->sconn;
5633
5634         START_PROFILE(SMBrmdir);
5635
5636         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5637                             STR_TERMINATE, &status);
5638         if (!NT_STATUS_IS_OK(status)) {
5639                 reply_nterror(req, status);
5640                 goto out;
5641         }
5642
5643         status = filename_convert(ctx, conn,
5644                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5645                                  directory,
5646                                  0,
5647                                  NULL,
5648                                  &smb_dname);
5649         if (!NT_STATUS_IS_OK(status)) {
5650                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5651                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5652                                         ERRSRV, ERRbadpath);
5653                         goto out;
5654                 }
5655                 reply_nterror(req, status);
5656                 goto out;
5657         }
5658
5659         if (is_ntfs_stream_smb_fname(smb_dname)) {
5660                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5661                 goto out;
5662         }
5663
5664         status = SMB_VFS_CREATE_FILE(
5665                 conn,                                   /* conn */
5666                 req,                                    /* req */
5667                 0,                                      /* root_dir_fid */
5668                 smb_dname,                              /* fname */
5669                 DELETE_ACCESS,                          /* access_mask */
5670                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5671                         FILE_SHARE_DELETE),
5672                 FILE_OPEN,                              /* create_disposition*/
5673                 FILE_DIRECTORY_FILE,                    /* create_options */
5674                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5675                 0,                                      /* oplock_request */
5676                 0,                                      /* allocation_size */
5677                 0,                                      /* private_flags */
5678                 NULL,                                   /* sd */
5679                 NULL,                                   /* ea_list */
5680                 &fsp,                                   /* result */
5681                 &info);                                 /* pinfo */
5682
5683         if (!NT_STATUS_IS_OK(status)) {
5684                 if (open_was_deferred(req->sconn, req->mid)) {
5685                         /* We have re-scheduled this call. */
5686                         goto out;
5687                 }
5688                 reply_nterror(req, status);
5689                 goto out;
5690         }
5691
5692         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5693         if (!NT_STATUS_IS_OK(status)) {
5694                 close_file(req, fsp, ERROR_CLOSE);
5695                 reply_nterror(req, status);
5696                 goto out;
5697         }
5698
5699         if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5700                 close_file(req, fsp, ERROR_CLOSE);
5701                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5702                 goto out;
5703         }
5704
5705         status = close_file(req, fsp, NORMAL_CLOSE);
5706         if (!NT_STATUS_IS_OK(status)) {
5707                 reply_nterror(req, status);
5708         } else {
5709                 reply_outbuf(req, 0, 0);
5710         }
5711
5712         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5713
5714         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5715  out:
5716         TALLOC_FREE(smb_dname);
5717         END_PROFILE(SMBrmdir);
5718         return;
5719 }
5720
5721 /*******************************************************************
5722  Resolve wildcards in a filename rename.
5723 ********************************************************************/
5724
5725 static bool resolve_wildcards(TALLOC_CTX *ctx,
5726                                 const char *name1,
5727                                 const char *name2,
5728                                 char **pp_newname)
5729 {
5730         char *name2_copy = NULL;
5731         char *root1 = NULL;
5732         char *root2 = NULL;
5733         char *ext1 = NULL;
5734         char *ext2 = NULL;
5735         char *p,*p2, *pname1, *pname2;
5736
5737         name2_copy = talloc_strdup(ctx, name2);
5738         if (!name2_copy) {
5739                 return False;
5740         }
5741
5742         pname1 = strrchr_m(name1,'/');
5743         pname2 = strrchr_m(name2_copy,'/');
5744
5745         if (!pname1 || !pname2) {
5746                 return False;
5747         }
5748
5749         /* Truncate the copy of name2 at the last '/' */
5750         *pname2 = '\0';
5751
5752         /* Now go past the '/' */
5753         pname1++;
5754         pname2++;
5755
5756         root1 = talloc_strdup(ctx, pname1);
5757         root2 = talloc_strdup(ctx, pname2);
5758
5759         if (!root1 || !root2) {
5760                 return False;
5761         }
5762
5763         p = strrchr_m(root1,'.');
5764         if (p) {
5765                 *p = 0;
5766                 ext1 = talloc_strdup(ctx, p+1);
5767         } else {
5768                 ext1 = talloc_strdup(ctx, "");
5769         }
5770         p = strrchr_m(root2,'.');
5771         if (p) {
5772                 *p = 0;
5773                 ext2 = talloc_strdup(ctx, p+1);
5774         } else {
5775                 ext2 = talloc_strdup(ctx, "");
5776         }
5777
5778         if (!ext1 || !ext2) {
5779                 return False;
5780         }
5781
5782         p = root1;
5783         p2 = root2;
5784         while (*p2) {
5785                 if (*p2 == '?') {
5786                         /* Hmmm. Should this be mb-aware ? */
5787                         *p2 = *p;
5788                         p2++;
5789                 } else if (*p2 == '*') {
5790                         *p2 = '\0';
5791                         root2 = talloc_asprintf(ctx, "%s%s",
5792                                                 root2,
5793                                                 p);
5794                         if (!root2) {
5795                                 return False;
5796                         }
5797                         break;
5798                 } else {
5799                         p2++;
5800                 }
5801                 if (*p) {
5802                         p++;
5803                 }
5804         }
5805
5806         p = ext1;
5807         p2 = ext2;
5808         while (*p2) {
5809                 if (*p2 == '?') {
5810                         /* Hmmm. Should this be mb-aware ? */
5811                         *p2 = *p;
5812                         p2++;
5813                 } else if (*p2 == '*') {
5814                         *p2 = '\0';
5815                         ext2 = talloc_asprintf(ctx, "%s%s",
5816                                                 ext2,
5817                                                 p);
5818                         if (!ext2) {
5819                                 return False;
5820                         }
5821                         break;
5822                 } else {
5823                         p2++;
5824                 }
5825                 if (*p) {
5826                         p++;
5827                 }
5828         }
5829
5830         if (*ext2) {
5831                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5832                                 name2_copy,
5833                                 root2,
5834                                 ext2);
5835         } else {
5836                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5837                                 name2_copy,
5838                                 root2);
5839         }
5840
5841         if (!*pp_newname) {
5842                 return False;
5843         }
5844
5845         return True;
5846 }
5847
5848 /****************************************************************************
5849  Ensure open files have their names updated. Updated to notify other smbd's
5850  asynchronously.
5851 ****************************************************************************/
5852
5853 static void rename_open_files(connection_struct *conn,
5854                               struct share_mode_lock *lck,
5855                               uint32_t orig_name_hash,
5856                               const struct smb_filename *smb_fname_dst)
5857 {
5858         files_struct *fsp;
5859         bool did_rename = False;
5860         NTSTATUS status;
5861         uint32_t new_name_hash = 0;
5862
5863         for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5864             fsp = file_find_di_next(fsp)) {
5865                 /* fsp_name is a relative path under the fsp. To change this for other
5866                    sharepaths we need to manipulate relative paths. */
5867                 /* TODO - create the absolute path and manipulate the newname
5868                    relative to the sharepath. */
5869                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5870                         continue;
5871                 }
5872                 if (fsp->name_hash != orig_name_hash) {
5873                         continue;
5874                 }
5875                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5876                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5877                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5878                            smb_fname_str_dbg(smb_fname_dst)));
5879
5880                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5881                 if (NT_STATUS_IS_OK(status)) {
5882                         did_rename = True;
5883                         new_name_hash = fsp->name_hash;
5884                 }
5885         }
5886
5887         if (!did_rename) {
5888                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5889                            "for %s\n", file_id_string_tos(&lck->id),
5890                            smb_fname_str_dbg(smb_fname_dst)));
5891         }
5892
5893         /* Send messages to all smbd's (not ourself) that the name has changed. */
5894         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5895                               orig_name_hash, new_name_hash,
5896                               smb_fname_dst);
5897
5898 }
5899
5900 /****************************************************************************
5901  We need to check if the source path is a parent directory of the destination
5902  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5903  refuse the rename with a sharing violation. Under UNIX the above call can
5904  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5905  probably need to check that the client is a Windows one before disallowing
5906  this as a UNIX client (one with UNIX extensions) can know the source is a
5907  symlink and make this decision intelligently. Found by an excellent bug
5908  report from <AndyLiebman@aol.com>.
5909 ****************************************************************************/
5910
5911 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5912                                      const struct smb_filename *smb_fname_dst)
5913 {
5914         const char *psrc = smb_fname_src->base_name;
5915         const char *pdst = smb_fname_dst->base_name;
5916         size_t slen;
5917
5918         if (psrc[0] == '.' && psrc[1] == '/') {
5919                 psrc += 2;
5920         }
5921         if (pdst[0] == '.' && pdst[1] == '/') {
5922                 pdst += 2;
5923         }
5924         if ((slen = strlen(psrc)) > strlen(pdst)) {
5925                 return False;
5926         }
5927         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5928 }
5929
5930 /*
5931  * Do the notify calls from a rename
5932  */
5933
5934 static void notify_rename(connection_struct *conn, bool is_dir,
5935                           const struct smb_filename *smb_fname_src,
5936                           const struct smb_filename *smb_fname_dst)
5937 {
5938         char *parent_dir_src = NULL;
5939         char *parent_dir_dst = NULL;
5940         uint32 mask;
5941
5942         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5943                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5944
5945         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5946                             &parent_dir_src, NULL) ||
5947             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5948                             &parent_dir_dst, NULL)) {
5949                 goto out;
5950         }
5951
5952         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5953                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5954                              smb_fname_src->base_name);
5955                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5956                              smb_fname_dst->base_name);
5957         }
5958         else {
5959                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5960                              smb_fname_src->base_name);
5961                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5962                              smb_fname_dst->base_name);
5963         }
5964
5965         /* this is a strange one. w2k3 gives an additional event for
5966            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5967            files, but not directories */
5968         if (!is_dir) {
5969                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5970                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5971                              |FILE_NOTIFY_CHANGE_CREATION,
5972                              smb_fname_dst->base_name);
5973         }
5974  out:
5975         TALLOC_FREE(parent_dir_src);
5976         TALLOC_FREE(parent_dir_dst);
5977 }
5978
5979 /****************************************************************************
5980  Returns an error if the parent directory for a filename is open in an
5981  incompatible way.
5982 ****************************************************************************/
5983
5984 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5985                                         const struct smb_filename *smb_fname_dst_in)
5986 {
5987         char *parent_dir = NULL;
5988         struct smb_filename smb_fname_parent;
5989         struct file_id id;
5990         files_struct *fsp = NULL;
5991         int ret;
5992
5993         if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5994                         &parent_dir, NULL)) {
5995                 return NT_STATUS_NO_MEMORY;
5996         }
5997         ZERO_STRUCT(smb_fname_parent);
5998         smb_fname_parent.base_name = parent_dir;
5999
6000         ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6001         if (ret == -1) {
6002                 return map_nt_error_from_unix(errno);
6003         }
6004
6005         /*
6006          * We're only checking on this smbd here, mostly good
6007          * enough.. and will pass tests.
6008          */
6009
6010         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6011         for (fsp = file_find_di_first(conn->sconn, id); fsp;
6012                         fsp = file_find_di_next(fsp)) {
6013                 if (fsp->access_mask & DELETE_ACCESS) {
6014                         return NT_STATUS_SHARING_VIOLATION;
6015                 }
6016         }
6017         return NT_STATUS_OK;
6018 }
6019
6020 /****************************************************************************
6021  Rename an open file - given an fsp.
6022 ****************************************************************************/
6023
6024 NTSTATUS rename_internals_fsp(connection_struct *conn,
6025                         files_struct *fsp,
6026                         const struct smb_filename *smb_fname_dst_in,
6027                         uint32 attrs,
6028                         bool replace_if_exists)
6029 {
6030         TALLOC_CTX *ctx = talloc_tos();
6031         struct smb_filename *smb_fname_dst = NULL;
6032         NTSTATUS status = NT_STATUS_OK;
6033         struct share_mode_lock *lck = NULL;
6034         bool dst_exists, old_is_stream, new_is_stream;
6035
6036         status = check_name(conn, smb_fname_dst_in->base_name);
6037         if (!NT_STATUS_IS_OK(status)) {
6038                 return status;
6039         }
6040
6041         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6042         if (!NT_STATUS_IS_OK(status)) {
6043                 return status;
6044         }
6045
6046         /* Make a copy of the dst smb_fname structs */
6047
6048         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6049         if (!NT_STATUS_IS_OK(status)) {
6050                 goto out;
6051         }
6052
6053         /*
6054          * Check for special case with case preserving and not
6055          * case sensitive. If the old last component differs from the original
6056          * last component only by case, then we should allow
6057          * the rename (user is trying to change the case of the
6058          * filename).
6059          */
6060         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6061             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6062             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6063                 char *last_slash;
6064                 char *fname_dst_lcomp_base_mod = NULL;
6065                 struct smb_filename *smb_fname_orig_lcomp = NULL;
6066
6067                 /*
6068                  * Get the last component of the destination name.
6069                  */
6070                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6071                 if (last_slash) {
6072                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6073                 } else {
6074                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6075                 }
6076                 if (!fname_dst_lcomp_base_mod) {
6077                         status = NT_STATUS_NO_MEMORY;
6078                         goto out;
6079                 }
6080
6081                 /*
6082                  * Create an smb_filename struct using the original last
6083                  * component of the destination.
6084                  */
6085                 status = create_synthetic_smb_fname_split(ctx,
6086                     smb_fname_dst->original_lcomp, NULL,
6087                     &smb_fname_orig_lcomp);
6088                 if (!NT_STATUS_IS_OK(status)) {
6089                         TALLOC_FREE(fname_dst_lcomp_base_mod);
6090                         goto out;
6091                 }
6092
6093                 /* If the base names only differ by case, use original. */
6094                 if(!strcsequal(fname_dst_lcomp_base_mod,
6095                                smb_fname_orig_lcomp->base_name)) {
6096                         char *tmp;
6097                         /*
6098                          * Replace the modified last component with the
6099                          * original.
6100                          */
6101                         if (last_slash) {
6102                                 *last_slash = '\0'; /* Truncate at the '/' */
6103                                 tmp = talloc_asprintf(smb_fname_dst,
6104                                         "%s/%s",
6105                                         smb_fname_dst->base_name,
6106                                         smb_fname_orig_lcomp->base_name);
6107                         } else {
6108                                 tmp = talloc_asprintf(smb_fname_dst,
6109                                         "%s",
6110                                         smb_fname_orig_lcomp->base_name);
6111                         }
6112                         if (tmp == NULL) {
6113                                 status = NT_STATUS_NO_MEMORY;
6114                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6115                                 TALLOC_FREE(smb_fname_orig_lcomp);
6116                                 goto out;
6117                         }
6118                         TALLOC_FREE(smb_fname_dst->base_name);
6119                         smb_fname_dst->base_name = tmp;
6120                 }
6121
6122                 /* If the stream_names only differ by case, use original. */
6123                 if(!strcsequal(smb_fname_dst->stream_name,
6124                                smb_fname_orig_lcomp->stream_name)) {
6125                         char *tmp = NULL;
6126                         /* Use the original stream. */
6127                         tmp = talloc_strdup(smb_fname_dst,
6128                                             smb_fname_orig_lcomp->stream_name);
6129                         if (tmp == NULL) {
6130                                 status = NT_STATUS_NO_MEMORY;
6131                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6132                                 TALLOC_FREE(smb_fname_orig_lcomp);
6133                                 goto out;
6134                         }
6135                         TALLOC_FREE(smb_fname_dst->stream_name);
6136                         smb_fname_dst->stream_name = tmp;
6137                 }
6138                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6139                 TALLOC_FREE(smb_fname_orig_lcomp);
6140         }
6141
6142         /*
6143          * If the src and dest names are identical - including case,
6144          * don't do the rename, just return success.
6145          */
6146
6147         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6148             strcsequal(fsp->fsp_name->stream_name,
6149                        smb_fname_dst->stream_name)) {
6150                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6151                           "- returning success\n",
6152                           smb_fname_str_dbg(smb_fname_dst)));
6153                 status = NT_STATUS_OK;
6154                 goto out;
6155         }
6156
6157         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6158         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6159
6160         /* Return the correct error code if both names aren't streams. */
6161         if (!old_is_stream && new_is_stream) {
6162                 status = NT_STATUS_OBJECT_NAME_INVALID;
6163                 goto out;
6164         }
6165
6166         if (old_is_stream && !new_is_stream) {
6167                 status = NT_STATUS_INVALID_PARAMETER;
6168                 goto out;
6169         }
6170
6171         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6172
6173         if(!replace_if_exists && dst_exists) {
6174                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6175                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6176                           smb_fname_str_dbg(smb_fname_dst)));
6177                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6178                 goto out;
6179         }
6180
6181         if (dst_exists) {
6182                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6183                     &smb_fname_dst->st);
6184                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6185                                                            fileid);
6186                 /* The file can be open when renaming a stream */
6187                 if (dst_fsp && !new_is_stream) {
6188                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6189                         status = NT_STATUS_ACCESS_DENIED;
6190                         goto out;
6191                 }
6192         }
6193
6194         /* Ensure we have a valid stat struct for the source. */
6195         status = vfs_stat_fsp(fsp);
6196         if (!NT_STATUS_IS_OK(status)) {
6197                 goto out;
6198         }
6199
6200         status = can_rename(conn, fsp, attrs);
6201
6202         if (!NT_STATUS_IS_OK(status)) {
6203                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6204                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6205                           smb_fname_str_dbg(smb_fname_dst)));
6206                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6207                         status = NT_STATUS_ACCESS_DENIED;
6208                 goto out;
6209         }
6210
6211         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6212                 status = NT_STATUS_ACCESS_DENIED;
6213         }
6214
6215         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6216                                   NULL);
6217
6218         /*
6219          * We have the file open ourselves, so not being able to get the
6220          * corresponding share mode lock is a fatal error.
6221          */
6222
6223         SMB_ASSERT(lck != NULL);
6224
6225         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6226                 uint32 create_options = fsp->fh->private_options;
6227
6228                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6229                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6230                           smb_fname_str_dbg(smb_fname_dst)));
6231
6232                 if (!lp_posix_pathnames() &&
6233                     (lp_map_archive(SNUM(conn)) ||
6234                     lp_store_dos_attributes(SNUM(conn)))) {
6235                         /* We must set the archive bit on the newly
6236                            renamed file. */
6237                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6238                                 uint32_t old_dosmode = dos_mode(conn,
6239                                                         smb_fname_dst);
6240                                 file_set_dosmode(conn,
6241                                         smb_fname_dst,
6242                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6243                                         NULL,
6244                                         true);
6245                         }
6246                 }
6247
6248                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6249                               smb_fname_dst);
6250
6251                 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6252
6253                 /*
6254                  * A rename acts as a new file create w.r.t. allowing an initial delete
6255                  * on close, probably because in Windows there is a new handle to the
6256                  * new file. If initial delete on close was requested but not
6257                  * originally set, we need to set it here. This is probably not 100% correct,
6258                  * but will work for the CIFSFS client which in non-posix mode
6259                  * depends on these semantics. JRA.
6260                  */
6261
6262                 if (create_options & FILE_DELETE_ON_CLOSE) {
6263                         status = can_set_delete_on_close(fsp, 0);
6264
6265                         if (NT_STATUS_IS_OK(status)) {
6266                                 /* Note that here we set the *inital* delete on close flag,
6267                                  * not the regular one. The magic gets handled in close. */
6268                                 fsp->initial_delete_on_close = True;
6269                         }
6270                 }
6271                 TALLOC_FREE(lck);
6272                 status = NT_STATUS_OK;
6273                 goto out;
6274         }
6275
6276         TALLOC_FREE(lck);
6277
6278         if (errno == ENOTDIR || errno == EISDIR) {
6279                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6280         } else {
6281                 status = map_nt_error_from_unix(errno);
6282         }
6283
6284         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6285                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6286                   smb_fname_str_dbg(smb_fname_dst)));
6287
6288  out:
6289         TALLOC_FREE(smb_fname_dst);
6290
6291         return status;
6292 }
6293
6294 /****************************************************************************
6295  The guts of the rename command, split out so it may be called by the NT SMB
6296  code.
6297 ****************************************************************************/
6298
6299 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6300                         connection_struct *conn,
6301                         struct smb_request *req,
6302                         struct smb_filename *smb_fname_src,
6303                         struct smb_filename *smb_fname_dst,
6304                         uint32 attrs,
6305                         bool replace_if_exists,
6306                         bool src_has_wild,
6307                         bool dest_has_wild,
6308                         uint32_t access_mask)
6309 {
6310         char *fname_src_dir = NULL;
6311         char *fname_src_mask = NULL;
6312         int count=0;
6313         NTSTATUS status = NT_STATUS_OK;
6314         struct smb_Dir *dir_hnd = NULL;
6315         const char *dname = NULL;
6316         char *talloced = NULL;
6317         long offset = 0;
6318         int create_options = 0;
6319         bool posix_pathnames = lp_posix_pathnames();
6320
6321         /*
6322          * Split the old name into directory and last component
6323          * strings. Note that unix_convert may have stripped off a
6324          * leading ./ from both name and newname if the rename is
6325          * at the root of the share. We need to make sure either both
6326          * name and newname contain a / character or neither of them do
6327          * as this is checked in resolve_wildcards().
6328          */
6329
6330         /* Split up the directory from the filename/mask. */
6331         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6332                                       &fname_src_dir, &fname_src_mask);
6333         if (!NT_STATUS_IS_OK(status)) {
6334                 status = NT_STATUS_NO_MEMORY;
6335                 goto out;
6336         }
6337
6338         /*
6339          * We should only check the mangled cache
6340          * here if unix_convert failed. This means
6341          * that the path in 'mask' doesn't exist
6342          * on the file system and so we need to look
6343          * for a possible mangle. This patch from
6344          * Tine Smukavec <valentin.smukavec@hermes.si>.
6345          */
6346
6347         if (!VALID_STAT(smb_fname_src->st) &&
6348             mangle_is_mangled(fname_src_mask, conn->params)) {
6349                 char *new_mask = NULL;
6350                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6351                                             conn->params);
6352                 if (new_mask) {
6353                         TALLOC_FREE(fname_src_mask);
6354                         fname_src_mask = new_mask;
6355                 }
6356         }
6357
6358         if (!src_has_wild) {
6359                 files_struct *fsp;
6360
6361                 /*
6362                  * Only one file needs to be renamed. Append the mask back
6363                  * onto the directory.
6364                  */
6365                 TALLOC_FREE(smb_fname_src->base_name);
6366                 if (ISDOT(fname_src_dir)) {
6367                         /* Ensure we use canonical names on open. */
6368                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6369                                                         "%s",
6370                                                         fname_src_mask);
6371                 } else {
6372                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6373                                                         "%s/%s",
6374                                                         fname_src_dir,
6375                                                         fname_src_mask);
6376                 }
6377                 if (!smb_fname_src->base_name) {
6378                         status = NT_STATUS_NO_MEMORY;
6379                         goto out;
6380                 }
6381
6382                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6383                           "case_preserve = %d, short case preserve = %d, "
6384                           "directory = %s, newname = %s, "
6385                           "last_component_dest = %s\n",
6386                           conn->case_sensitive, conn->case_preserve,
6387                           conn->short_case_preserve,
6388                           smb_fname_str_dbg(smb_fname_src),
6389                           smb_fname_str_dbg(smb_fname_dst),
6390                           smb_fname_dst->original_lcomp));
6391
6392                 /* The dest name still may have wildcards. */
6393                 if (dest_has_wild) {
6394                         char *fname_dst_mod = NULL;
6395                         if (!resolve_wildcards(smb_fname_dst,
6396                                                smb_fname_src->base_name,
6397                                                smb_fname_dst->base_name,
6398                                                &fname_dst_mod)) {
6399                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6400                                           "%s %s failed\n",
6401                                           smb_fname_src->base_name,
6402                                           smb_fname_dst->base_name));
6403                                 status = NT_STATUS_NO_MEMORY;
6404                                 goto out;
6405                         }
6406                         TALLOC_FREE(smb_fname_dst->base_name);
6407                         smb_fname_dst->base_name = fname_dst_mod;
6408                 }
6409
6410                 ZERO_STRUCT(smb_fname_src->st);
6411                 if (posix_pathnames) {
6412                         SMB_VFS_LSTAT(conn, smb_fname_src);
6413                 } else {
6414                         SMB_VFS_STAT(conn, smb_fname_src);
6415                 }
6416
6417                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6418                         create_options |= FILE_DIRECTORY_FILE;
6419                 }
6420
6421                 status = SMB_VFS_CREATE_FILE(
6422                         conn,                           /* conn */
6423                         req,                            /* req */
6424                         0,                              /* root_dir_fid */
6425                         smb_fname_src,                  /* fname */
6426                         access_mask,                    /* access_mask */
6427                         (FILE_SHARE_READ |              /* share_access */
6428                             FILE_SHARE_WRITE),
6429                         FILE_OPEN,                      /* create_disposition*/
6430                         create_options,                 /* create_options */
6431                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6432                         0,                              /* oplock_request */
6433                         0,                              /* allocation_size */
6434                         0,                              /* private_flags */
6435                         NULL,                           /* sd */
6436                         NULL,                           /* ea_list */
6437                         &fsp,                           /* result */
6438                         NULL);                          /* pinfo */
6439
6440                 if (!NT_STATUS_IS_OK(status)) {
6441                         DEBUG(3, ("Could not open rename source %s: %s\n",
6442                                   smb_fname_str_dbg(smb_fname_src),
6443                                   nt_errstr(status)));
6444                         goto out;
6445                 }
6446
6447                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6448                                               attrs, replace_if_exists);
6449
6450                 close_file(req, fsp, NORMAL_CLOSE);
6451
6452                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6453                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6454                           smb_fname_str_dbg(smb_fname_dst)));
6455
6456                 goto out;
6457         }
6458
6459         /*
6460          * Wildcards - process each file that matches.
6461          */
6462         if (strequal(fname_src_mask, "????????.???")) {
6463                 TALLOC_FREE(fname_src_mask);
6464                 fname_src_mask = talloc_strdup(ctx, "*");
6465                 if (!fname_src_mask) {
6466                         status = NT_STATUS_NO_MEMORY;
6467                         goto out;
6468                 }
6469         }
6470
6471         status = check_name(conn, fname_src_dir);
6472         if (!NT_STATUS_IS_OK(status)) {
6473                 goto out;
6474         }
6475
6476         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6477                           attrs);
6478         if (dir_hnd == NULL) {
6479                 status = map_nt_error_from_unix(errno);
6480                 goto out;
6481         }
6482
6483         status = NT_STATUS_NO_SUCH_FILE;
6484         /*
6485          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6486          * - gentest fix. JRA
6487          */
6488
6489         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6490                                     &talloced))) {
6491                 files_struct *fsp = NULL;
6492                 char *destname = NULL;
6493                 bool sysdir_entry = False;
6494
6495                 /* Quick check for "." and ".." */
6496                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6497                         if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6498                                 sysdir_entry = True;
6499                         } else {
6500                                 TALLOC_FREE(talloced);
6501                                 continue;
6502                         }
6503                 }
6504
6505                 if (!is_visible_file(conn, fname_src_dir, dname,
6506                                      &smb_fname_src->st, false)) {
6507                         TALLOC_FREE(talloced);
6508                         continue;
6509                 }
6510
6511                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6512                         TALLOC_FREE(talloced);
6513                         continue;
6514                 }
6515
6516                 if (sysdir_entry) {
6517                         status = NT_STATUS_OBJECT_NAME_INVALID;
6518                         break;
6519                 }
6520
6521                 TALLOC_FREE(smb_fname_src->base_name);
6522                 if (ISDOT(fname_src_dir)) {
6523                         /* Ensure we use canonical names on open. */
6524                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6525                                                         "%s",
6526                                                         dname);
6527                 } else {
6528                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6529                                                         "%s/%s",
6530                                                         fname_src_dir,
6531                                                         dname);
6532                 }
6533                 if (!smb_fname_src->base_name) {
6534                         status = NT_STATUS_NO_MEMORY;
6535                         goto out;
6536                 }
6537
6538                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6539                                        smb_fname_dst->base_name,
6540                                        &destname)) {
6541                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6542                                   smb_fname_src->base_name, destname));
6543                         TALLOC_FREE(talloced);
6544                         continue;
6545                 }
6546                 if (!destname) {
6547                         status = NT_STATUS_NO_MEMORY;
6548                         goto out;
6549                 }
6550
6551                 TALLOC_FREE(smb_fname_dst->base_name);
6552                 smb_fname_dst->base_name = destname;
6553
6554                 ZERO_STRUCT(smb_fname_src->st);
6555                 if (posix_pathnames) {
6556                         SMB_VFS_LSTAT(conn, smb_fname_src);
6557                 } else {
6558                         SMB_VFS_STAT(conn, smb_fname_src);
6559                 }
6560
6561                 create_options = 0;
6562
6563                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6564                         create_options |= FILE_DIRECTORY_FILE;
6565                 }
6566
6567                 status = SMB_VFS_CREATE_FILE(
6568                         conn,                           /* conn */
6569                         req,                            /* req */
6570                         0,                              /* root_dir_fid */
6571                         smb_fname_src,                  /* fname */
6572                         access_mask,                    /* access_mask */
6573                         (FILE_SHARE_READ |              /* share_access */
6574                             FILE_SHARE_WRITE),
6575                         FILE_OPEN,                      /* create_disposition*/
6576                         create_options,                 /* create_options */
6577                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6578                         0,                              /* oplock_request */
6579                         0,                              /* allocation_size */
6580                         0,                              /* private_flags */
6581                         NULL,                           /* sd */
6582                         NULL,                           /* ea_list */
6583                         &fsp,                           /* result */
6584                         NULL);                          /* pinfo */
6585
6586                 if (!NT_STATUS_IS_OK(status)) {
6587                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6588                                  "returned %s rename %s -> %s\n",
6589                                  nt_errstr(status),
6590                                  smb_fname_str_dbg(smb_fname_src),
6591                                  smb_fname_str_dbg(smb_fname_dst)));
6592                         break;
6593                 }
6594
6595                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6596                                                               dname);
6597                 if (!smb_fname_dst->original_lcomp) {
6598                         status = NT_STATUS_NO_MEMORY;
6599                         goto out;
6600                 }
6601
6602                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6603                                               attrs, replace_if_exists);
6604
6605                 close_file(req, fsp, NORMAL_CLOSE);
6606
6607                 if (!NT_STATUS_IS_OK(status)) {
6608                         DEBUG(3, ("rename_internals_fsp returned %s for "
6609                                   "rename %s -> %s\n", nt_errstr(status),
6610                                   smb_fname_str_dbg(smb_fname_src),
6611                                   smb_fname_str_dbg(smb_fname_dst)));
6612                         break;
6613                 }
6614
6615                 count++;
6616
6617                 DEBUG(3,("rename_internals: doing rename on %s -> "
6618                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6619                          smb_fname_str_dbg(smb_fname_src)));
6620                 TALLOC_FREE(talloced);
6621         }
6622         TALLOC_FREE(dir_hnd);
6623
6624         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6625                 status = map_nt_error_from_unix(errno);
6626         }
6627
6628  out:
6629         TALLOC_FREE(talloced);
6630         TALLOC_FREE(fname_src_dir);
6631         TALLOC_FREE(fname_src_mask);
6632         return status;
6633 }
6634
6635 /****************************************************************************
6636  Reply to a mv.
6637 ****************************************************************************/
6638
6639 void reply_mv(struct smb_request *req)
6640 {
6641         connection_struct *conn = req->conn;
6642         char *name = NULL;
6643         char *newname = NULL;
6644         const char *p;
6645         uint32 attrs;
6646         NTSTATUS status;
6647         bool src_has_wcard = False;
6648         bool dest_has_wcard = False;
6649         TALLOC_CTX *ctx = talloc_tos();
6650         struct smb_filename *smb_fname_src = NULL;
6651         struct smb_filename *smb_fname_dst = NULL;
6652         uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6653         uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6654         bool stream_rename = false;
6655
6656         START_PROFILE(SMBmv);
6657
6658         if (req->wct < 1) {
6659                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6660                 goto out;
6661         }
6662
6663         attrs = SVAL(req->vwv+0, 0);
6664
6665         p = (const char *)req->buf + 1;
6666         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6667                                        &status, &src_has_wcard);
6668         if (!NT_STATUS_IS_OK(status)) {
6669                 reply_nterror(req, status);
6670                 goto out;
6671         }
6672         p++;
6673         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6674                                        &status, &dest_has_wcard);
6675         if (!NT_STATUS_IS_OK(status)) {
6676                 reply_nterror(req, status);
6677                 goto out;
6678         }
6679
6680         if (!lp_posix_pathnames()) {
6681                 /* The newname must begin with a ':' if the
6682                    name contains a ':'. */
6683                 if (strchr_m(name, ':')) {
6684                         if (newname[0] != ':') {
6685                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6686                                 goto out;
6687                         }
6688                         stream_rename = true;
6689                 }
6690         }
6691
6692         status = filename_convert(ctx,
6693                                   conn,
6694                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6695                                   name,
6696                                   src_ucf_flags,
6697                                   &src_has_wcard,
6698                                   &smb_fname_src);
6699
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6702                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6703                                         ERRSRV, ERRbadpath);
6704                         goto out;
6705                 }
6706                 reply_nterror(req, status);
6707                 goto out;
6708         }
6709
6710         status = filename_convert(ctx,
6711                                   conn,
6712                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6713                                   newname,
6714                                   dst_ucf_flags,
6715                                   &dest_has_wcard,
6716                                   &smb_fname_dst);
6717
6718         if (!NT_STATUS_IS_OK(status)) {
6719                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6720                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6721                                         ERRSRV, ERRbadpath);
6722                         goto out;
6723                 }
6724                 reply_nterror(req, status);
6725                 goto out;
6726         }
6727
6728         if (stream_rename) {
6729                 /* smb_fname_dst->base_name must be the same as
6730                    smb_fname_src->base_name. */
6731                 TALLOC_FREE(smb_fname_dst->base_name);
6732                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6733                                                 smb_fname_src->base_name);
6734                 if (!smb_fname_dst->base_name) {
6735                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6736                         goto out;
6737                 }
6738         }
6739
6740         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6741                  smb_fname_str_dbg(smb_fname_dst)));
6742
6743         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6744                                   attrs, False, src_has_wcard, dest_has_wcard,
6745                                   DELETE_ACCESS);
6746         if (!NT_STATUS_IS_OK(status)) {
6747                 if (open_was_deferred(req->sconn, req->mid)) {
6748                         /* We have re-scheduled this call. */
6749                         goto out;
6750                 }
6751                 reply_nterror(req, status);
6752                 goto out;
6753         }
6754
6755         reply_outbuf(req, 0, 0);
6756  out:
6757         TALLOC_FREE(smb_fname_src);
6758         TALLOC_FREE(smb_fname_dst);
6759         END_PROFILE(SMBmv);
6760         return;
6761 }
6762
6763 /*******************************************************************
6764  Copy a file as part of a reply_copy.
6765 ******************************************************************/
6766
6767 /*
6768  * TODO: check error codes on all callers
6769  */
6770
6771 NTSTATUS copy_file(TALLOC_CTX *ctx,
6772                         connection_struct *conn,
6773                         struct smb_filename *smb_fname_src,
6774                         struct smb_filename *smb_fname_dst,
6775                         int ofun,
6776                         int count,
6777                         bool target_is_directory)
6778 {
6779         struct smb_filename *smb_fname_dst_tmp = NULL;
6780         SMB_OFF_T ret=-1;
6781         files_struct *fsp1,*fsp2;
6782         uint32 dosattrs;
6783         uint32 new_create_disposition;
6784         NTSTATUS status;
6785
6786
6787         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6788         if (!NT_STATUS_IS_OK(status)) {
6789                 return status;
6790         }
6791
6792         /*
6793          * If the target is a directory, extract the last component from the
6794          * src filename and append it to the dst filename
6795          */
6796         if (target_is_directory) {
6797                 const char *p;
6798
6799                 /* dest/target can't be a stream if it's a directory. */
6800                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6801
6802                 p = strrchr_m(smb_fname_src->base_name,'/');
6803                 if (p) {
6804                         p++;
6805                 } else {
6806                         p = smb_fname_src->base_name;
6807                 }
6808                 smb_fname_dst_tmp->base_name =
6809                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6810                                            p);
6811                 if (!smb_fname_dst_tmp->base_name) {
6812                         status = NT_STATUS_NO_MEMORY;
6813                         goto out;
6814                 }
6815         }
6816
6817         status = vfs_file_exist(conn, smb_fname_src);
6818         if (!NT_STATUS_IS_OK(status)) {
6819                 goto out;
6820         }
6821
6822         if (!target_is_directory && count) {
6823                 new_create_disposition = FILE_OPEN;
6824         } else {
6825                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6826                                                  0, ofun,
6827                                                  NULL, NULL,
6828                                                  &new_create_disposition,
6829                                                  NULL,
6830                                                  NULL)) {
6831                         status = NT_STATUS_INVALID_PARAMETER;
6832                         goto out;
6833                 }
6834         }
6835
6836         /* Open the src file for reading. */
6837         status = SMB_VFS_CREATE_FILE(
6838                 conn,                                   /* conn */
6839                 NULL,                                   /* req */
6840                 0,                                      /* root_dir_fid */
6841                 smb_fname_src,                          /* fname */
6842                 FILE_GENERIC_READ,                      /* access_mask */
6843                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6844                 FILE_OPEN,                              /* create_disposition*/
6845                 0,                                      /* create_options */
6846                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6847                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6848                 0,                                      /* allocation_size */
6849                 0,                                      /* private_flags */
6850                 NULL,                                   /* sd */
6851                 NULL,                                   /* ea_list */
6852                 &fsp1,                                  /* result */
6853                 NULL);                                  /* psbuf */
6854
6855         if (!NT_STATUS_IS_OK(status)) {
6856                 goto out;
6857         }
6858
6859         dosattrs = dos_mode(conn, smb_fname_src);
6860
6861         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6862                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6863         }
6864
6865         /* Open the dst file for writing. */
6866         status = SMB_VFS_CREATE_FILE(
6867                 conn,                                   /* conn */
6868                 NULL,                                   /* req */
6869                 0,                                      /* root_dir_fid */
6870                 smb_fname_dst,                          /* fname */
6871                 FILE_GENERIC_WRITE,                     /* access_mask */
6872                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6873                 new_create_disposition,                 /* create_disposition*/
6874                 0,                                      /* create_options */
6875                 dosattrs,                               /* file_attributes */
6876                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6877                 0,                                      /* allocation_size */
6878                 0,                                      /* private_flags */
6879                 NULL,                                   /* sd */
6880                 NULL,                                   /* ea_list */
6881                 &fsp2,                                  /* result */
6882                 NULL);                                  /* psbuf */
6883
6884         if (!NT_STATUS_IS_OK(status)) {
6885                 close_file(NULL, fsp1, ERROR_CLOSE);
6886                 goto out;
6887         }
6888
6889         if (ofun & OPENX_FILE_EXISTS_OPEN) {
6890                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6891                 if (ret == -1) {
6892                         DEBUG(0, ("error - vfs lseek returned error %s\n",
6893                                 strerror(errno)));
6894                         status = map_nt_error_from_unix(errno);
6895                         close_file(NULL, fsp1, ERROR_CLOSE);
6896                         close_file(NULL, fsp2, ERROR_CLOSE);
6897                         goto out;
6898                 }
6899         }
6900
6901         /* Do the actual copy. */
6902         if (smb_fname_src->st.st_ex_size) {
6903                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6904         } else {
6905                 ret = 0;
6906         }
6907
6908         close_file(NULL, fsp1, NORMAL_CLOSE);
6909
6910         /* Ensure the modtime is set correctly on the destination file. */
6911         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6912
6913         /*
6914          * As we are opening fsp1 read-only we only expect
6915          * an error on close on fsp2 if we are out of space.
6916          * Thus we don't look at the error return from the
6917          * close of fsp1.
6918          */
6919         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6920
6921         if (!NT_STATUS_IS_OK(status)) {
6922                 goto out;
6923         }
6924
6925         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6926                 status = NT_STATUS_DISK_FULL;
6927                 goto out;
6928         }
6929
6930         status = NT_STATUS_OK;
6931
6932  out:
6933         TALLOC_FREE(smb_fname_dst_tmp);
6934         return status;
6935 }
6936
6937 /****************************************************************************
6938  Reply to a file copy.
6939 ****************************************************************************/
6940
6941 void reply_copy(struct smb_request *req)
6942 {
6943         connection_struct *conn = req->conn;
6944         struct smb_filename *smb_fname_src = NULL;
6945         struct smb_filename *smb_fname_dst = NULL;
6946         char *fname_src = NULL;
6947         char *fname_dst = NULL;
6948         char *fname_src_mask = NULL;
6949         char *fname_src_dir = NULL;
6950         const char *p;
6951         int count=0;
6952         int error = ERRnoaccess;
6953         int tid2;
6954         int ofun;
6955         int flags;
6956         bool target_is_directory=False;
6957         bool source_has_wild = False;
6958         bool dest_has_wild = False;
6959         NTSTATUS status;
6960         TALLOC_CTX *ctx = talloc_tos();
6961
6962         START_PROFILE(SMBcopy);
6963
6964         if (req->wct < 3) {
6965                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6966                 goto out;
6967         }
6968
6969         tid2 = SVAL(req->vwv+0, 0);
6970         ofun = SVAL(req->vwv+1, 0);
6971         flags = SVAL(req->vwv+2, 0);
6972
6973         p = (const char *)req->buf;
6974         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6975                                        &status, &source_has_wild);
6976         if (!NT_STATUS_IS_OK(status)) {
6977                 reply_nterror(req, status);
6978                 goto out;
6979         }
6980         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6981                                        &status, &dest_has_wild);
6982         if (!NT_STATUS_IS_OK(status)) {
6983                 reply_nterror(req, status);
6984                 goto out;
6985         }
6986
6987         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6988
6989         if (tid2 != conn->cnum) {
6990                 /* can't currently handle inter share copies XXXX */
6991                 DEBUG(3,("Rejecting inter-share copy\n"));
6992                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6993                 goto out;
6994         }
6995
6996         status = filename_convert(ctx, conn,
6997                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6998                                   fname_src,
6999                                   UCF_COND_ALLOW_WCARD_LCOMP,
7000                                   &source_has_wild,
7001                                   &smb_fname_src);
7002         if (!NT_STATUS_IS_OK(status)) {
7003                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7004                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7005                                         ERRSRV, ERRbadpath);
7006                         goto out;
7007                 }
7008                 reply_nterror(req, status);
7009                 goto out;
7010         }
7011
7012         status = filename_convert(ctx, conn,
7013                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
7014                                   fname_dst,
7015                                   UCF_COND_ALLOW_WCARD_LCOMP,
7016                                   &dest_has_wild,
7017                                   &smb_fname_dst);
7018         if (!NT_STATUS_IS_OK(status)) {
7019                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7020                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7021                                         ERRSRV, ERRbadpath);
7022                         goto out;
7023                 }
7024                 reply_nterror(req, status);
7025                 goto out;
7026         }
7027
7028         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7029
7030         if ((flags&1) && target_is_directory) {
7031                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7032                 goto out;
7033         }
7034
7035         if ((flags&2) && !target_is_directory) {
7036                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7037                 goto out;
7038         }
7039
7040         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7041                 /* wants a tree copy! XXXX */
7042                 DEBUG(3,("Rejecting tree copy\n"));
7043                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7044                 goto out;
7045         }
7046
7047         /* Split up the directory from the filename/mask. */
7048         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7049                                       &fname_src_dir, &fname_src_mask);
7050         if (!NT_STATUS_IS_OK(status)) {
7051                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7052                 goto out;
7053         }
7054
7055         /*
7056          * We should only check the mangled cache
7057          * here if unix_convert failed. This means
7058          * that the path in 'mask' doesn't exist
7059          * on the file system and so we need to look
7060          * for a possible mangle. This patch from
7061          * Tine Smukavec <valentin.smukavec@hermes.si>.
7062          */
7063         if (!VALID_STAT(smb_fname_src->st) &&
7064             mangle_is_mangled(fname_src_mask, conn->params)) {
7065                 char *new_mask = NULL;
7066                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7067                                             &new_mask, conn->params);
7068
7069                 /* Use demangled name if one was successfully found. */
7070                 if (new_mask) {
7071                         TALLOC_FREE(fname_src_mask);
7072                         fname_src_mask = new_mask;
7073                 }
7074         }
7075
7076         if (!source_has_wild) {
7077
7078                 /*
7079                  * Only one file needs to be copied. Append the mask back onto
7080                  * the directory.
7081                  */
7082                 TALLOC_FREE(smb_fname_src->base_name);
7083                 if (ISDOT(fname_src_dir)) {
7084                         /* Ensure we use canonical names on open. */
7085                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7086                                                         "%s",
7087                                                         fname_src_mask);
7088                 } else {
7089                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7090                                                         "%s/%s",
7091                                                         fname_src_dir,
7092                                                         fname_src_mask);
7093                 }
7094                 if (!smb_fname_src->base_name) {
7095                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7096                         goto out;
7097                 }
7098
7099                 if (dest_has_wild) {
7100                         char *fname_dst_mod = NULL;
7101                         if (!resolve_wildcards(smb_fname_dst,
7102                                                smb_fname_src->base_name,
7103                                                smb_fname_dst->base_name,
7104                                                &fname_dst_mod)) {
7105                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7106                                 goto out;
7107                         }
7108                         TALLOC_FREE(smb_fname_dst->base_name);
7109                         smb_fname_dst->base_name = fname_dst_mod;
7110                 }
7111
7112                 status = check_name(conn, smb_fname_src->base_name);
7113                 if (!NT_STATUS_IS_OK(status)) {
7114                         reply_nterror(req, status);
7115                         goto out;
7116                 }
7117
7118                 status = check_name(conn, smb_fname_dst->base_name);
7119                 if (!NT_STATUS_IS_OK(status)) {
7120                         reply_nterror(req, status);
7121                         goto out;
7122                 }
7123
7124                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7125                                    ofun, count, target_is_directory);
7126
7127                 if(!NT_STATUS_IS_OK(status)) {
7128                         reply_nterror(req, status);
7129                         goto out;
7130                 } else {
7131                         count++;
7132                 }
7133         } else {
7134                 struct smb_Dir *dir_hnd = NULL;
7135                 const char *dname = NULL;
7136                 char *talloced = NULL;
7137                 long offset = 0;
7138
7139                 /*
7140                  * There is a wildcard that requires us to actually read the
7141                  * src dir and copy each file matching the mask to the dst.
7142                  * Right now streams won't be copied, but this could
7143                  * presumably be added with a nested loop for reach dir entry.
7144                  */
7145                 SMB_ASSERT(!smb_fname_src->stream_name);
7146                 SMB_ASSERT(!smb_fname_dst->stream_name);
7147
7148                 smb_fname_src->stream_name = NULL;
7149                 smb_fname_dst->stream_name = NULL;
7150
7151                 if (strequal(fname_src_mask,"????????.???")) {
7152                         TALLOC_FREE(fname_src_mask);
7153                         fname_src_mask = talloc_strdup(ctx, "*");
7154                         if (!fname_src_mask) {
7155                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7156                                 goto out;
7157                         }
7158                 }
7159
7160                 status = check_name(conn, fname_src_dir);
7161                 if (!NT_STATUS_IS_OK(status)) {
7162                         reply_nterror(req, status);
7163                         goto out;
7164                 }
7165
7166                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7167                 if (dir_hnd == NULL) {
7168                         status = map_nt_error_from_unix(errno);
7169                         reply_nterror(req, status);
7170                         goto out;
7171                 }
7172
7173                 error = ERRbadfile;
7174
7175                 /* Iterate over the src dir copying each entry to the dst. */
7176                 while ((dname = ReadDirName(dir_hnd, &offset,
7177                                             &smb_fname_src->st, &talloced))) {
7178                         char *destname = NULL;
7179
7180                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7181                                 TALLOC_FREE(talloced);
7182                                 continue;
7183                         }
7184
7185                         if (!is_visible_file(conn, fname_src_dir, dname,
7186                                              &smb_fname_src->st, false)) {
7187                                 TALLOC_FREE(talloced);
7188                                 continue;
7189                         }
7190
7191                         if(!mask_match(dname, fname_src_mask,
7192                                        conn->case_sensitive)) {
7193                                 TALLOC_FREE(talloced);
7194                                 continue;
7195                         }
7196
7197                         error = ERRnoaccess;
7198
7199                         /* Get the src smb_fname struct setup. */
7200                         TALLOC_FREE(smb_fname_src->base_name);
7201                         if (ISDOT(fname_src_dir)) {
7202                                 /* Ensure we use canonical names on open. */
7203                                 smb_fname_src->base_name =
7204                                         talloc_asprintf(smb_fname_src, "%s",
7205                                                 dname);
7206                         } else {
7207                                 smb_fname_src->base_name =
7208                                         talloc_asprintf(smb_fname_src, "%s/%s",
7209                                                 fname_src_dir, dname);
7210                         }
7211
7212                         if (!smb_fname_src->base_name) {
7213                                 TALLOC_FREE(dir_hnd);
7214                                 TALLOC_FREE(talloced);
7215                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7216                                 goto out;
7217                         }
7218
7219                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7220                                                smb_fname_dst->base_name,
7221                                                &destname)) {
7222                                 TALLOC_FREE(talloced);
7223                                 continue;
7224                         }
7225                         if (!destname) {
7226                                 TALLOC_FREE(dir_hnd);
7227                                 TALLOC_FREE(talloced);
7228                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7229                                 goto out;
7230                         }
7231
7232                         TALLOC_FREE(smb_fname_dst->base_name);
7233                         smb_fname_dst->base_name = destname;
7234
7235                         status = check_name(conn, smb_fname_src->base_name);
7236                         if (!NT_STATUS_IS_OK(status)) {
7237                                 TALLOC_FREE(dir_hnd);
7238                                 TALLOC_FREE(talloced);
7239                                 reply_nterror(req, status);
7240                                 goto out;
7241                         }
7242
7243                         status = check_name(conn, smb_fname_dst->base_name);
7244                         if (!NT_STATUS_IS_OK(status)) {
7245                                 TALLOC_FREE(dir_hnd);
7246                                 TALLOC_FREE(talloced);
7247                                 reply_nterror(req, status);
7248                                 goto out;
7249                         }
7250
7251                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7252                                 smb_fname_src->base_name,
7253                                 smb_fname_dst->base_name));
7254
7255                         status = copy_file(ctx, conn, smb_fname_src,
7256                                            smb_fname_dst, ofun, count,
7257                                            target_is_directory);
7258                         if (NT_STATUS_IS_OK(status)) {
7259                                 count++;
7260                         }
7261
7262                         TALLOC_FREE(talloced);
7263                 }
7264                 TALLOC_FREE(dir_hnd);
7265         }
7266
7267         if (count == 0) {
7268                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7269                 goto out;
7270         }
7271
7272         reply_outbuf(req, 1, 0);
7273         SSVAL(req->outbuf,smb_vwv0,count);
7274  out:
7275         TALLOC_FREE(smb_fname_src);
7276         TALLOC_FREE(smb_fname_dst);
7277         TALLOC_FREE(fname_src);
7278         TALLOC_FREE(fname_dst);
7279         TALLOC_FREE(fname_src_mask);
7280         TALLOC_FREE(fname_src_dir);
7281
7282         END_PROFILE(SMBcopy);
7283         return;
7284 }
7285
7286 #undef DBGC_CLASS
7287 #define DBGC_CLASS DBGC_LOCKING
7288
7289 /****************************************************************************
7290  Get a lock pid, dealing with large count requests.
7291 ****************************************************************************/
7292
7293 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7294                     bool large_file_format)
7295 {
7296         if(!large_file_format)
7297                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7298         else
7299                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7300 }
7301
7302 /****************************************************************************
7303  Get a lock count, dealing with large count requests.
7304 ****************************************************************************/
7305
7306 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7307                         bool large_file_format)
7308 {
7309         uint64_t count = 0;
7310
7311         if(!large_file_format) {
7312                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7313         } else {
7314
7315 #if defined(HAVE_LONGLONG)
7316                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7317                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7318 #else /* HAVE_LONGLONG */
7319
7320                 /*
7321                  * NT4.x seems to be broken in that it sends large file (64 bit)
7322                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7323                  * negotiated. For boxes without large unsigned ints truncate the
7324                  * lock count by dropping the top 32 bits.
7325                  */
7326
7327                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7328                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7329                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7330                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7331                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7332                 }
7333
7334                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7335 #endif /* HAVE_LONGLONG */
7336         }
7337
7338         return count;
7339 }
7340
7341 #if !defined(HAVE_LONGLONG)
7342 /****************************************************************************
7343  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7344 ****************************************************************************/
7345
7346 static uint32 map_lock_offset(uint32 high, uint32 low)
7347 {
7348         unsigned int i;
7349         uint32 mask = 0;
7350         uint32 highcopy = high;
7351
7352         /*
7353          * Try and find out how many significant bits there are in high.
7354          */
7355
7356         for(i = 0; highcopy; i++)
7357                 highcopy >>= 1;
7358
7359         /*
7360          * We use 31 bits not 32 here as POSIX
7361          * lock offsets may not be negative.
7362          */
7363
7364         mask = (~0) << (31 - i);
7365
7366         if(low & mask)
7367                 return 0; /* Fail. */
7368
7369         high <<= (31 - i);
7370
7371         return (high|low);
7372 }
7373 #endif /* !defined(HAVE_LONGLONG) */
7374
7375 /****************************************************************************
7376  Get a lock offset, dealing with large offset requests.
7377 ****************************************************************************/
7378
7379 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7380                          bool large_file_format, bool *err)
7381 {
7382         uint64_t offset = 0;
7383
7384         *err = False;
7385
7386         if(!large_file_format) {
7387                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7388         } else {
7389
7390 #if defined(HAVE_LONGLONG)
7391                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7392                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7393 #else /* HAVE_LONGLONG */
7394
7395                 /*
7396                  * NT4.x seems to be broken in that it sends large file (64 bit)
7397                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7398                  * negotiated. For boxes without large unsigned ints mangle the
7399                  * lock offset by mapping the top 32 bits onto the lower 32.
7400                  */
7401
7402                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7403                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7404                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7405                         uint32 new_low = 0;
7406
7407                         if((new_low = map_lock_offset(high, low)) == 0) {
7408                                 *err = True;
7409                                 return (uint64_t)-1;
7410                         }
7411
7412                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7413                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7414                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7415                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7416                 }
7417
7418                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7419 #endif /* HAVE_LONGLONG */
7420         }
7421
7422         return offset;
7423 }
7424
7425 NTSTATUS smbd_do_locking(struct smb_request *req,
7426                          files_struct *fsp,
7427                          uint8_t type,
7428                          int32_t timeout,
7429                          uint16_t num_ulocks,
7430                          struct smbd_lock_element *ulocks,
7431                          uint16_t num_locks,
7432                          struct smbd_lock_element *locks,
7433                          bool *async)
7434 {
7435         connection_struct *conn = req->conn;
7436         int i;
7437         NTSTATUS status = NT_STATUS_OK;
7438
7439         *async = false;
7440
7441         /* Data now points at the beginning of the list
7442            of smb_unlkrng structs */
7443         for(i = 0; i < (int)num_ulocks; i++) {
7444                 struct smbd_lock_element *e = &ulocks[i];
7445
7446                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7447                           "pid %u, file %s\n",
7448                           (double)e->offset,
7449                           (double)e->count,
7450                           (unsigned int)e->smblctx,
7451                           fsp_str_dbg(fsp)));
7452
7453                 if (e->brltype != UNLOCK_LOCK) {
7454                         /* this can only happen with SMB2 */
7455                         return NT_STATUS_INVALID_PARAMETER;
7456                 }
7457
7458                 status = do_unlock(req->sconn->msg_ctx,
7459                                 fsp,
7460                                 e->smblctx,
7461                                 e->count,
7462                                 e->offset,
7463                                 WINDOWS_LOCK);
7464
7465                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7466                     nt_errstr(status)));
7467
7468                 if (!NT_STATUS_IS_OK(status)) {
7469                         return status;
7470                 }
7471         }
7472
7473         /* Setup the timeout in seconds. */
7474
7475         if (!lp_blocking_locks(SNUM(conn))) {
7476                 timeout = 0;
7477         }
7478
7479         /* Data now points at the beginning of the list
7480            of smb_lkrng structs */
7481
7482         for(i = 0; i < (int)num_locks; i++) {
7483                 struct smbd_lock_element *e = &locks[i];
7484
7485                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7486                           "%llu, file %s timeout = %d\n",
7487                           (double)e->offset,
7488                           (double)e->count,
7489                           (unsigned long long)e->smblctx,
7490                           fsp_str_dbg(fsp),
7491                           (int)timeout));
7492
7493                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7494                         struct blocking_lock_record *blr = NULL;
7495
7496                         if (num_locks > 1) {
7497                                 /*
7498                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7499                                  * if the lock vector contains one entry. When given mutliple cancel
7500                                  * requests in a single PDU we expect the server to return an
7501                                  * error. Windows servers seem to accept the request but only
7502                                  * cancel the first lock.
7503                                  * JRA - Do what Windows does (tm) :-).
7504                                  */
7505
7506 #if 0
7507                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7508                                 return NT_STATUS_DOS(ERRDOS,
7509                                                 ERRcancelviolation);
7510 #else
7511                                 /* Windows behavior. */
7512                                 if (i != 0) {
7513                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7514                                                 "cancel request\n"));
7515                                         continue;
7516                                 }
7517 #endif
7518                         }
7519
7520                         if (lp_blocking_locks(SNUM(conn))) {
7521
7522                                 /* Schedule a message to ourselves to
7523                                    remove the blocking lock record and
7524                                    return the right error. */
7525
7526                                 blr = blocking_lock_cancel_smb1(fsp,
7527                                                 e->smblctx,
7528                                                 e->offset,
7529                                                 e->count,
7530                                                 WINDOWS_LOCK,
7531                                                 type,
7532                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7533                                 if (blr == NULL) {
7534                                         return NT_STATUS_DOS(
7535                                                         ERRDOS,
7536                                                         ERRcancelviolation);
7537                                 }
7538                         }
7539                         /* Remove a matching pending lock. */
7540                         status = do_lock_cancel(fsp,
7541                                                 e->smblctx,
7542                                                 e->count,
7543                                                 e->offset,
7544                                                 WINDOWS_LOCK,
7545                                                 blr);
7546                 } else {
7547                         bool blocking_lock = timeout ? true : false;
7548                         bool defer_lock = false;
7549                         struct byte_range_lock *br_lck;
7550                         uint64_t block_smblctx;
7551
7552                         br_lck = do_lock(req->sconn->msg_ctx,
7553                                         fsp,
7554                                         e->smblctx,
7555                                         e->count,
7556                                         e->offset, 
7557                                         e->brltype,
7558                                         WINDOWS_LOCK,
7559                                         blocking_lock,
7560                                         &status,
7561                                         &block_smblctx,
7562                                         NULL);
7563
7564                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7565                                 /* Windows internal resolution for blocking locks seems
7566                                    to be about 200ms... Don't wait for less than that. JRA. */
7567                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7568                                         timeout = lp_lock_spin_time();
7569                                 }
7570                                 defer_lock = true;
7571                         }
7572
7573                         /* If a lock sent with timeout of zero would fail, and
7574                          * this lock has been requested multiple times,
7575                          * according to brl_lock_failed() we convert this
7576                          * request to a blocking lock with a timeout of between
7577                          * 150 - 300 milliseconds.
7578                          *
7579                          * If lp_lock_spin_time() has been set to 0, we skip
7580                          * this blocking retry and fail immediately.
7581                          *
7582                          * Replacement for do_lock_spin(). JRA. */
7583
7584                         if (!req->sconn->using_smb2 &&
7585                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7586                             lp_lock_spin_time() && !blocking_lock &&
7587                             NT_STATUS_EQUAL((status),
7588                                 NT_STATUS_FILE_LOCK_CONFLICT))
7589                         {
7590                                 defer_lock = true;
7591                                 timeout = lp_lock_spin_time();
7592                         }
7593
7594                         if (br_lck && defer_lock) {
7595                                 /*
7596                                  * A blocking lock was requested. Package up
7597                                  * this smb into a queued request and push it
7598                                  * onto the blocking lock queue.
7599                                  */
7600                                 if(push_blocking_lock_request(br_lck,
7601                                                         req,
7602                                                         fsp,
7603                                                         timeout,
7604                                                         i,
7605                                                         e->smblctx,
7606                                                         e->brltype,
7607                                                         WINDOWS_LOCK,
7608                                                         e->offset,
7609                                                         e->count,
7610                                                         block_smblctx)) {
7611                                         TALLOC_FREE(br_lck);
7612                                         *async = true;
7613                                         return NT_STATUS_OK;
7614                                 }
7615                         }
7616
7617                         TALLOC_FREE(br_lck);
7618                 }
7619
7620                 if (!NT_STATUS_IS_OK(status)) {
7621                         break;
7622                 }
7623         }
7624
7625         /* If any of the above locks failed, then we must unlock
7626            all of the previous locks (X/Open spec). */
7627
7628         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7629
7630                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7631                         i = -1; /* we want to skip the for loop */
7632                 }
7633
7634                 /*
7635                  * Ensure we don't do a remove on the lock that just failed,
7636                  * as under POSIX rules, if we have a lock already there, we
7637                  * will delete it (and we shouldn't) .....
7638                  */
7639                 for(i--; i >= 0; i--) {
7640                         struct smbd_lock_element *e = &locks[i];
7641
7642                         do_unlock(req->sconn->msg_ctx,
7643                                 fsp,
7644                                 e->smblctx,
7645                                 e->count,
7646                                 e->offset,
7647                                 WINDOWS_LOCK);
7648                 }
7649                 return status;
7650         }
7651
7652         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7653                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7654
7655         return NT_STATUS_OK;
7656 }
7657
7658 /****************************************************************************
7659  Reply to a lockingX request.
7660 ****************************************************************************/
7661
7662 void reply_lockingX(struct smb_request *req)
7663 {
7664         connection_struct *conn = req->conn;
7665         files_struct *fsp;
7666         unsigned char locktype;
7667         unsigned char oplocklevel;
7668         uint16 num_ulocks;
7669         uint16 num_locks;
7670         int32 lock_timeout;
7671         int i;
7672         const uint8_t *data;
7673         bool large_file_format;
7674         bool err;
7675         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7676         struct smbd_lock_element *ulocks;
7677         struct smbd_lock_element *locks;
7678         bool async = false;
7679
7680         START_PROFILE(SMBlockingX);
7681
7682         if (req->wct < 8) {
7683                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7684                 END_PROFILE(SMBlockingX);
7685                 return;
7686         }
7687
7688         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7689         locktype = CVAL(req->vwv+3, 0);
7690         oplocklevel = CVAL(req->vwv+3, 1);
7691         num_ulocks = SVAL(req->vwv+6, 0);
7692         num_locks = SVAL(req->vwv+7, 0);
7693         lock_timeout = IVAL(req->vwv+4, 0);
7694         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7695
7696         if (!check_fsp(conn, req, fsp)) {
7697                 END_PROFILE(SMBlockingX);
7698                 return;
7699         }
7700
7701         data = req->buf;
7702
7703         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7704                 /* we don't support these - and CANCEL_LOCK makes w2k
7705                    and XP reboot so I don't really want to be
7706                    compatible! (tridge) */
7707                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7708                 END_PROFILE(SMBlockingX);
7709                 return;
7710         }
7711
7712         /* Check if this is an oplock break on a file
7713            we have granted an oplock on.
7714         */
7715         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7716                 /* Client can insist on breaking to none. */
7717                 bool break_to_none = (oplocklevel == 0);
7718                 bool result;
7719
7720                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7721                          "for fnum = %d\n", (unsigned int)oplocklevel,
7722                          fsp->fnum ));
7723
7724                 /*
7725                  * Make sure we have granted an exclusive or batch oplock on
7726                  * this file.
7727                  */
7728
7729                 if (fsp->oplock_type == 0) {
7730
7731                         /* The Samba4 nbench simulator doesn't understand
7732                            the difference between break to level2 and break
7733                            to none from level2 - it sends oplock break
7734                            replies in both cases. Don't keep logging an error
7735                            message here - just ignore it. JRA. */
7736
7737                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7738                                  "client for fnum = %d (oplock=%d) and no "
7739                                  "oplock granted on this file (%s).\n",
7740                                  fsp->fnum, fsp->oplock_type,
7741                                  fsp_str_dbg(fsp)));
7742
7743                         /* if this is a pure oplock break request then don't
7744                          * send a reply */
7745                         if (num_locks == 0 && num_ulocks == 0) {
7746                                 END_PROFILE(SMBlockingX);
7747                                 return;
7748                         } else {
7749                                 END_PROFILE(SMBlockingX);
7750                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7751                                 return;
7752                         }
7753                 }
7754
7755                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7756                     (break_to_none)) {
7757                         result = remove_oplock(fsp);
7758                 } else {
7759                         result = downgrade_oplock(fsp);
7760                 }
7761
7762                 if (!result) {
7763                         DEBUG(0, ("reply_lockingX: error in removing "
7764                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7765                         /* Hmmm. Is this panic justified? */
7766                         smb_panic("internal tdb error");
7767                 }
7768
7769                 reply_to_oplock_break_requests(fsp);
7770
7771                 /* if this is a pure oplock break request then don't send a
7772                  * reply */
7773                 if (num_locks == 0 && num_ulocks == 0) {
7774                         /* Sanity check - ensure a pure oplock break is not a
7775                            chained request. */
7776                         if(CVAL(req->vwv+0, 0) != 0xff)
7777                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7778                                          "break is a chained %d request !\n",
7779                                          (unsigned int)CVAL(req->vwv+0, 0)));
7780                         END_PROFILE(SMBlockingX);
7781                         return;
7782                 }
7783         }
7784
7785         if (req->buflen <
7786             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7787                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7788                 END_PROFILE(SMBlockingX);
7789                 return;
7790         }
7791
7792         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7793         if (ulocks == NULL) {
7794                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7795                 END_PROFILE(SMBlockingX);
7796                 return;
7797         }
7798
7799         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7800         if (locks == NULL) {
7801                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7802                 END_PROFILE(SMBlockingX);
7803                 return;
7804         }
7805
7806         /* Data now points at the beginning of the list
7807            of smb_unlkrng structs */
7808         for(i = 0; i < (int)num_ulocks; i++) {
7809                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7810                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7811                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7812                 ulocks[i].brltype = UNLOCK_LOCK;
7813
7814                 /*
7815                  * There is no error code marked "stupid client bug".... :-).
7816                  */
7817                 if(err) {
7818                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7819                         END_PROFILE(SMBlockingX);
7820                         return;
7821                 }
7822         }
7823
7824         /* Now do any requested locks */
7825         data += ((large_file_format ? 20 : 10)*num_ulocks);
7826
7827         /* Data now points at the beginning of the list
7828            of smb_lkrng structs */
7829
7830         for(i = 0; i < (int)num_locks; i++) {
7831                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7832                 locks[i].count = get_lock_count(data, i, large_file_format);
7833                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7834
7835                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7836                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7837                                 locks[i].brltype = PENDING_READ_LOCK;
7838                         } else {
7839                                 locks[i].brltype = READ_LOCK;
7840                         }
7841                 } else {
7842                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7843                                 locks[i].brltype = PENDING_WRITE_LOCK;
7844                         } else {
7845                                 locks[i].brltype = WRITE_LOCK;
7846                         }
7847                 }
7848
7849                 /*
7850                  * There is no error code marked "stupid client bug".... :-).
7851                  */
7852                 if(err) {
7853                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7854                         END_PROFILE(SMBlockingX);
7855                         return;
7856                 }
7857         }
7858
7859         status = smbd_do_locking(req, fsp,
7860                                  locktype, lock_timeout,
7861                                  num_ulocks, ulocks,
7862                                  num_locks, locks,
7863                                  &async);
7864         if (!NT_STATUS_IS_OK(status)) {
7865                 END_PROFILE(SMBlockingX);
7866                 reply_nterror(req, status);
7867                 return;
7868         }
7869         if (async) {
7870                 END_PROFILE(SMBlockingX);
7871                 return;
7872         }
7873
7874         reply_outbuf(req, 2, 0);
7875
7876         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7877                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7878
7879         END_PROFILE(SMBlockingX);
7880         chain_reply(req);
7881 }
7882
7883 #undef DBGC_CLASS
7884 #define DBGC_CLASS DBGC_ALL
7885
7886 /****************************************************************************
7887  Reply to a SMBreadbmpx (read block multiplex) request.
7888  Always reply with an error, if someone has a platform really needs this,
7889  please contact vl@samba.org
7890 ****************************************************************************/
7891
7892 void reply_readbmpx(struct smb_request *req)
7893 {
7894         START_PROFILE(SMBreadBmpx);
7895         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7896         END_PROFILE(SMBreadBmpx);
7897         return;
7898 }
7899
7900 /****************************************************************************
7901  Reply to a SMBreadbs (read block multiplex secondary) request.
7902  Always reply with an error, if someone has a platform really needs this,
7903  please contact vl@samba.org
7904 ****************************************************************************/
7905
7906 void reply_readbs(struct smb_request *req)
7907 {
7908         START_PROFILE(SMBreadBs);
7909         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7910         END_PROFILE(SMBreadBs);
7911         return;
7912 }
7913
7914 /****************************************************************************
7915  Reply to a SMBsetattrE.
7916 ****************************************************************************/
7917
7918 void reply_setattrE(struct smb_request *req)
7919 {
7920         connection_struct *conn = req->conn;
7921         struct smb_file_time ft;
7922         files_struct *fsp;
7923         NTSTATUS status;
7924
7925         START_PROFILE(SMBsetattrE);
7926         ZERO_STRUCT(ft);
7927
7928         if (req->wct < 7) {
7929                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930                 goto out;
7931         }
7932
7933         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7934
7935         if(!fsp || (fsp->conn != conn)) {
7936                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7937                 goto out;
7938         }
7939
7940         /*
7941          * Convert the DOS times into unix times.
7942          */
7943
7944         ft.atime = convert_time_t_to_timespec(
7945             srv_make_unix_date2(req->vwv+3));
7946         ft.mtime = convert_time_t_to_timespec(
7947             srv_make_unix_date2(req->vwv+5));
7948         ft.create_time = convert_time_t_to_timespec(
7949             srv_make_unix_date2(req->vwv+1));
7950
7951         reply_outbuf(req, 0, 0);
7952
7953         /* 
7954          * Patch from Ray Frush <frush@engr.colostate.edu>
7955          * Sometimes times are sent as zero - ignore them.
7956          */
7957
7958         /* Ensure we have a valid stat struct for the source. */
7959         status = vfs_stat_fsp(fsp);
7960         if (!NT_STATUS_IS_OK(status)) {
7961                 reply_nterror(req, status);
7962                 goto out;
7963         }
7964
7965         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7966                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7967                 goto out;
7968         }
7969
7970         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7971         if (!NT_STATUS_IS_OK(status)) {
7972                 reply_nterror(req, status);
7973                 goto out;
7974         }
7975
7976         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7977                " createtime=%u\n",
7978                 fsp->fnum,
7979                 (unsigned int)ft.atime.tv_sec,
7980                 (unsigned int)ft.mtime.tv_sec,
7981                 (unsigned int)ft.create_time.tv_sec
7982                 ));
7983  out:
7984         END_PROFILE(SMBsetattrE);
7985         return;
7986 }
7987
7988
7989 /* Back from the dead for OS/2..... JRA. */
7990
7991 /****************************************************************************
7992  Reply to a SMBwritebmpx (write block multiplex primary) request.
7993  Always reply with an error, if someone has a platform really needs this,
7994  please contact vl@samba.org
7995 ****************************************************************************/
7996
7997 void reply_writebmpx(struct smb_request *req)
7998 {
7999         START_PROFILE(SMBwriteBmpx);
8000         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8001         END_PROFILE(SMBwriteBmpx);
8002         return;
8003 }
8004
8005 /****************************************************************************
8006  Reply to a SMBwritebs (write block multiplex secondary) request.
8007  Always reply with an error, if someone has a platform really needs this,
8008  please contact vl@samba.org
8009 ****************************************************************************/
8010
8011 void reply_writebs(struct smb_request *req)
8012 {
8013         START_PROFILE(SMBwriteBs);
8014         reply_force_doserror(req, ERRSRV, ERRuseSTD);
8015         END_PROFILE(SMBwriteBs);
8016         return;
8017 }
8018
8019 /****************************************************************************
8020  Reply to a SMBgetattrE.
8021 ****************************************************************************/
8022
8023 void reply_getattrE(struct smb_request *req)
8024 {
8025         connection_struct *conn = req->conn;
8026         int mode;
8027         files_struct *fsp;
8028         struct timespec create_ts;
8029
8030         START_PROFILE(SMBgetattrE);
8031
8032         if (req->wct < 1) {
8033                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8034                 END_PROFILE(SMBgetattrE);
8035                 return;
8036         }
8037
8038         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8039
8040         if(!fsp || (fsp->conn != conn)) {
8041                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8042                 END_PROFILE(SMBgetattrE);
8043                 return;
8044         }
8045
8046         /* Do an fstat on this file */
8047         if(fsp_stat(fsp)) {
8048                 reply_nterror(req, map_nt_error_from_unix(errno));
8049                 END_PROFILE(SMBgetattrE);
8050                 return;
8051         }
8052
8053         mode = dos_mode(conn, fsp->fsp_name);
8054
8055         /*
8056          * Convert the times into dos times. Set create
8057          * date to be last modify date as UNIX doesn't save
8058          * this.
8059          */
8060
8061         reply_outbuf(req, 11, 0);
8062
8063         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8064         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8065         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8066                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8067         /* Should we check pending modtime here ? JRA */
8068         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8069                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8070
8071         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8072                 SIVAL(req->outbuf, smb_vwv6, 0);
8073                 SIVAL(req->outbuf, smb_vwv8, 0);
8074         } else {
8075                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8076                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8077                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8078         }
8079         SSVAL(req->outbuf,smb_vwv10, mode);
8080
8081         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8082
8083         END_PROFILE(SMBgetattrE);
8084         return;
8085 }