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