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