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