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