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