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