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