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