Remove all uses of "./" in pathnames - make canonical. This will become important...
[obnox/samba/samba-obnox.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/cli_spoolss.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, 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, 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(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
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 policy_handle handle;
5323                 struct spoolss_DevmodeContainer devmode_ctr;
5324                 union spoolss_JobInfo *info;
5325                 uint32_t count;
5326                 uint32_t num_to_get;
5327                 uint32_t first;
5328                 uint32_t i;
5329
5330                 ZERO_STRUCT(handle);
5331
5332                 status = rpc_pipe_open_interface(conn,
5333                                                  &ndr_table_spoolss.syntax_id,
5334                                                  conn->server_info,
5335                                                  &conn->sconn->client_id,
5336                                                  conn->sconn->msg_ctx,
5337                                                  &cli);
5338                 if (!NT_STATUS_IS_OK(status)) {
5339                         DEBUG(0, ("reply_printqueue: "
5340                                   "could not connect to spoolss: %s\n",
5341                                   nt_errstr(status)));
5342                         reply_nterror(req, status);
5343                         goto out;
5344                 }
5345
5346                 ZERO_STRUCT(devmode_ctr);
5347
5348                 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5349                                                 sharename,
5350                                                 NULL, devmode_ctr,
5351                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5352                                                 &handle,
5353                                                 &werr);
5354                 if (!NT_STATUS_IS_OK(status)) {
5355                         reply_nterror(req, status);
5356                         goto out;
5357                 }
5358                 if (!W_ERROR_IS_OK(werr)) {
5359                         reply_nterror(req, werror_to_ntstatus(werr));
5360                         goto out;
5361                 }
5362
5363                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5364                                                &handle,
5365                                                0, /* firstjob */
5366                                                0xff, /* numjobs */
5367                                                2, /* level */
5368                                                0, /* offered */
5369                                                &count,
5370                                                &info);
5371                 if (!W_ERROR_IS_OK(werr)) {
5372                         reply_nterror(req, werror_to_ntstatus(werr));
5373                         goto out;
5374                 }
5375
5376                 if (max_count > 0) {
5377                         first = start_index;
5378                 } else {
5379                         first = start_index + max_count + 1;
5380                 }
5381
5382                 if (first >= count) {
5383                         num_to_get = first;
5384                 } else {
5385                         num_to_get = first + MIN(ABS(max_count), count - first);
5386                 }
5387
5388                 for (i = first; i < num_to_get; i++) {
5389                         char blob[28];
5390                         char *p = blob;
5391                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5392                         int qstatus;
5393                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5394                                                         info[i].info2.job_id);
5395
5396                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5397                                 qstatus = 2;
5398                         } else {
5399                                 qstatus = 3;
5400                         }
5401
5402                         srv_put_dos_date2(p, 0, qtime);
5403                         SCVAL(p, 4, qstatus);
5404                         SSVAL(p, 5, qrapjobid);
5405                         SIVAL(p, 7, info[i].info2.size);
5406                         SCVAL(p, 11, 0);
5407                         srvstr_push(blob, req->flags2, p+12,
5408                                     info[i].info2.notify_name, 16, STR_ASCII);
5409
5410                         if (message_push_blob(
5411                                     &req->outbuf,
5412                                     data_blob_const(
5413                                             blob, sizeof(blob))) == -1) {
5414                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5415                                 goto out;
5416                         }
5417                 }
5418
5419                 if (count > 0) {
5420                         SSVAL(req->outbuf,smb_vwv0,count);
5421                         SSVAL(req->outbuf,smb_vwv1,
5422                               (max_count>0?first+count:first-1));
5423                         SCVAL(smb_buf(req->outbuf),0,1);
5424                         SSVAL(smb_buf(req->outbuf),1,28*count);
5425                 }
5426
5427
5428                 DEBUG(3, ("%u entries returned in queue\n",
5429                           (unsigned)count));
5430
5431 out:
5432                 if (cli && is_valid_policy_hnd(&handle)) {
5433                         rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5434                 }
5435
5436         }
5437
5438         END_PROFILE(SMBsplretq);
5439         return;
5440 }
5441
5442 /****************************************************************************
5443  Reply to a printwrite.
5444 ****************************************************************************/
5445
5446 void reply_printwrite(struct smb_request *req)
5447 {
5448         connection_struct *conn = req->conn;
5449         int numtowrite;
5450         const char *data;
5451         files_struct *fsp;
5452
5453         START_PROFILE(SMBsplwr);
5454
5455         if (req->wct < 1) {
5456                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5457                 END_PROFILE(SMBsplwr);
5458                 return;
5459         }
5460
5461         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5462
5463         if (!check_fsp(conn, req, fsp)) {
5464                 END_PROFILE(SMBsplwr);
5465                 return;
5466         }
5467
5468         if (!fsp->print_file) {
5469                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5470                 END_PROFILE(SMBsplwr);
5471                 return;
5472         }
5473
5474         if (!CHECK_WRITE(fsp)) {
5475                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5476                 END_PROFILE(SMBsplwr);
5477                 return;
5478         }
5479
5480         numtowrite = SVAL(req->buf, 1);
5481
5482         if (req->buflen < numtowrite + 3) {
5483                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5484                 END_PROFILE(SMBsplwr);
5485                 return;
5486         }
5487
5488         data = (const char *)req->buf + 3;
5489
5490         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5491                 reply_nterror(req, map_nt_error_from_unix(errno));
5492                 END_PROFILE(SMBsplwr);
5493                 return;
5494         }
5495
5496         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5497
5498         END_PROFILE(SMBsplwr);
5499         return;
5500 }
5501
5502 /****************************************************************************
5503  Reply to a mkdir.
5504 ****************************************************************************/
5505
5506 void reply_mkdir(struct smb_request *req)
5507 {
5508         connection_struct *conn = req->conn;
5509         struct smb_filename *smb_dname = NULL;
5510         char *directory = NULL;
5511         NTSTATUS status;
5512         TALLOC_CTX *ctx = talloc_tos();
5513
5514         START_PROFILE(SMBmkdir);
5515
5516         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5517                             STR_TERMINATE, &status);
5518         if (!NT_STATUS_IS_OK(status)) {
5519                 reply_nterror(req, status);
5520                 goto out;
5521         }
5522
5523         status = filename_convert(ctx, conn,
5524                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5525                                  directory,
5526                                  0,
5527                                  NULL,
5528                                  &smb_dname);
5529         if (!NT_STATUS_IS_OK(status)) {
5530                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5531                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5532                                         ERRSRV, ERRbadpath);
5533                         goto out;
5534                 }
5535                 reply_nterror(req, status);
5536                 goto out;
5537         }
5538
5539         status = create_directory(conn, req, smb_dname);
5540
5541         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5542
5543         if (!NT_STATUS_IS_OK(status)) {
5544
5545                 if (!use_nt_status()
5546                     && NT_STATUS_EQUAL(status,
5547                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5548                         /*
5549                          * Yes, in the DOS error code case we get a
5550                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5551                          * samba4 torture test.
5552                          */
5553                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5554                 }
5555
5556                 reply_nterror(req, status);
5557                 goto out;
5558         }
5559
5560         reply_outbuf(req, 0, 0);
5561
5562         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5563  out:
5564         TALLOC_FREE(smb_dname);
5565         END_PROFILE(SMBmkdir);
5566         return;
5567 }
5568
5569 /****************************************************************************
5570  Reply to a rmdir.
5571 ****************************************************************************/
5572
5573 void reply_rmdir(struct smb_request *req)
5574 {
5575         connection_struct *conn = req->conn;
5576         struct smb_filename *smb_dname = NULL;
5577         char *directory = NULL;
5578         NTSTATUS status;
5579         TALLOC_CTX *ctx = talloc_tos();
5580         files_struct *fsp = NULL;
5581         int info = 0;
5582         struct smbd_server_connection *sconn = req->sconn;
5583
5584         START_PROFILE(SMBrmdir);
5585
5586         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5587                             STR_TERMINATE, &status);
5588         if (!NT_STATUS_IS_OK(status)) {
5589                 reply_nterror(req, status);
5590                 goto out;
5591         }
5592
5593         status = filename_convert(ctx, conn,
5594                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5595                                  directory,
5596                                  0,
5597                                  NULL,
5598                                  &smb_dname);
5599         if (!NT_STATUS_IS_OK(status)) {
5600                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5601                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5602                                         ERRSRV, ERRbadpath);
5603                         goto out;
5604                 }
5605                 reply_nterror(req, status);
5606                 goto out;
5607         }
5608
5609         if (is_ntfs_stream_smb_fname(smb_dname)) {
5610                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5611                 goto out;
5612         }
5613
5614         status = SMB_VFS_CREATE_FILE(
5615                 conn,                                   /* conn */
5616                 req,                                    /* req */
5617                 0,                                      /* root_dir_fid */
5618                 smb_dname,                              /* fname */
5619                 DELETE_ACCESS,                          /* access_mask */
5620                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5621                         FILE_SHARE_DELETE),
5622                 FILE_OPEN,                              /* create_disposition*/
5623                 FILE_DIRECTORY_FILE,                    /* create_options */
5624                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5625                 0,                                      /* oplock_request */
5626                 0,                                      /* allocation_size */
5627                 0,                                      /* private_flags */
5628                 NULL,                                   /* sd */
5629                 NULL,                                   /* ea_list */
5630                 &fsp,                                   /* result */
5631                 &info);                                 /* pinfo */
5632
5633         if (!NT_STATUS_IS_OK(status)) {
5634                 if (open_was_deferred(req->mid)) {
5635                         /* We have re-scheduled this call. */
5636                         goto out;
5637                 }
5638                 reply_nterror(req, status);
5639                 goto out;
5640         }
5641
5642         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5643         if (!NT_STATUS_IS_OK(status)) {
5644                 close_file(req, fsp, ERROR_CLOSE);
5645                 reply_nterror(req, status);
5646                 goto out;
5647         }
5648
5649         if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5650                 close_file(req, fsp, ERROR_CLOSE);
5651                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5652                 goto out;
5653         }
5654
5655         status = close_file(req, fsp, NORMAL_CLOSE);
5656         if (!NT_STATUS_IS_OK(status)) {
5657                 reply_nterror(req, status);
5658         } else {
5659                 reply_outbuf(req, 0, 0);
5660         }
5661
5662         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5663
5664         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5665  out:
5666         TALLOC_FREE(smb_dname);
5667         END_PROFILE(SMBrmdir);
5668         return;
5669 }
5670
5671 /*******************************************************************
5672  Resolve wildcards in a filename rename.
5673 ********************************************************************/
5674
5675 static bool resolve_wildcards(TALLOC_CTX *ctx,
5676                                 const char *name1,
5677                                 const char *name2,
5678                                 char **pp_newname)
5679 {
5680         char *name2_copy = NULL;
5681         char *root1 = NULL;
5682         char *root2 = NULL;
5683         char *ext1 = NULL;
5684         char *ext2 = NULL;
5685         char *p,*p2, *pname1, *pname2;
5686
5687         name2_copy = talloc_strdup(ctx, name2);
5688         if (!name2_copy) {
5689                 return False;
5690         }
5691
5692         pname1 = strrchr_m(name1,'/');
5693         pname2 = strrchr_m(name2_copy,'/');
5694
5695         if (!pname1 || !pname2) {
5696                 return False;
5697         }
5698
5699         /* Truncate the copy of name2 at the last '/' */
5700         *pname2 = '\0';
5701
5702         /* Now go past the '/' */
5703         pname1++;
5704         pname2++;
5705
5706         root1 = talloc_strdup(ctx, pname1);
5707         root2 = talloc_strdup(ctx, pname2);
5708
5709         if (!root1 || !root2) {
5710                 return False;
5711         }
5712
5713         p = strrchr_m(root1,'.');
5714         if (p) {
5715                 *p = 0;
5716                 ext1 = talloc_strdup(ctx, p+1);
5717         } else {
5718                 ext1 = talloc_strdup(ctx, "");
5719         }
5720         p = strrchr_m(root2,'.');
5721         if (p) {
5722                 *p = 0;
5723                 ext2 = talloc_strdup(ctx, p+1);
5724         } else {
5725                 ext2 = talloc_strdup(ctx, "");
5726         }
5727
5728         if (!ext1 || !ext2) {
5729                 return False;
5730         }
5731
5732         p = root1;
5733         p2 = root2;
5734         while (*p2) {
5735                 if (*p2 == '?') {
5736                         /* Hmmm. Should this be mb-aware ? */
5737                         *p2 = *p;
5738                         p2++;
5739                 } else if (*p2 == '*') {
5740                         *p2 = '\0';
5741                         root2 = talloc_asprintf(ctx, "%s%s",
5742                                                 root2,
5743                                                 p);
5744                         if (!root2) {
5745                                 return False;
5746                         }
5747                         break;
5748                 } else {
5749                         p2++;
5750                 }
5751                 if (*p) {
5752                         p++;
5753                 }
5754         }
5755
5756         p = ext1;
5757         p2 = ext2;
5758         while (*p2) {
5759                 if (*p2 == '?') {
5760                         /* Hmmm. Should this be mb-aware ? */
5761                         *p2 = *p;
5762                         p2++;
5763                 } else if (*p2 == '*') {
5764                         *p2 = '\0';
5765                         ext2 = talloc_asprintf(ctx, "%s%s",
5766                                                 ext2,
5767                                                 p);
5768                         if (!ext2) {
5769                                 return False;
5770                         }
5771                         break;
5772                 } else {
5773                         p2++;
5774                 }
5775                 if (*p) {
5776                         p++;
5777                 }
5778         }
5779
5780         if (*ext2) {
5781                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5782                                 name2_copy,
5783                                 root2,
5784                                 ext2);
5785         } else {
5786                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5787                                 name2_copy,
5788                                 root2);
5789         }
5790
5791         if (!*pp_newname) {
5792                 return False;
5793         }
5794
5795         return True;
5796 }
5797
5798 /****************************************************************************
5799  Ensure open files have their names updated. Updated to notify other smbd's
5800  asynchronously.
5801 ****************************************************************************/
5802
5803 static void rename_open_files(connection_struct *conn,
5804                               struct share_mode_lock *lck,
5805                               const struct smb_filename *smb_fname_dst)
5806 {
5807         files_struct *fsp;
5808         bool did_rename = False;
5809         NTSTATUS status;
5810
5811         for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5812             fsp = file_find_di_next(fsp)) {
5813                 /* fsp_name is a relative path under the fsp. To change this for other
5814                    sharepaths we need to manipulate relative paths. */
5815                 /* TODO - create the absolute path and manipulate the newname
5816                    relative to the sharepath. */
5817                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5818                         continue;
5819                 }
5820                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5821                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5822                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5823                            smb_fname_str_dbg(smb_fname_dst)));
5824
5825                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5826                 if (NT_STATUS_IS_OK(status)) {
5827                         did_rename = True;
5828                 }
5829         }
5830
5831         if (!did_rename) {
5832                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5833                            "for %s\n", file_id_string_tos(&lck->id),
5834                            smb_fname_str_dbg(smb_fname_dst)));
5835         }
5836
5837         /* Send messages to all smbd's (not ourself) that the name has changed. */
5838         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5839                               smb_fname_dst);
5840
5841 }
5842
5843 /****************************************************************************
5844  We need to check if the source path is a parent directory of the destination
5845  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5846  refuse the rename with a sharing violation. Under UNIX the above call can
5847  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5848  probably need to check that the client is a Windows one before disallowing
5849  this as a UNIX client (one with UNIX extensions) can know the source is a
5850  symlink and make this decision intelligently. Found by an excellent bug
5851  report from <AndyLiebman@aol.com>.
5852 ****************************************************************************/
5853
5854 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5855                                      const struct smb_filename *smb_fname_dst)
5856 {
5857         const char *psrc = smb_fname_src->base_name;
5858         const char *pdst = smb_fname_dst->base_name;
5859         size_t slen;
5860
5861         if (psrc[0] == '.' && psrc[1] == '/') {
5862                 psrc += 2;
5863         }
5864         if (pdst[0] == '.' && pdst[1] == '/') {
5865                 pdst += 2;
5866         }
5867         if ((slen = strlen(psrc)) > strlen(pdst)) {
5868                 return False;
5869         }
5870         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5871 }
5872
5873 /*
5874  * Do the notify calls from a rename
5875  */
5876
5877 static void notify_rename(connection_struct *conn, bool is_dir,
5878                           const struct smb_filename *smb_fname_src,
5879                           const struct smb_filename *smb_fname_dst)
5880 {
5881         char *parent_dir_src = NULL;
5882         char *parent_dir_dst = NULL;
5883         uint32 mask;
5884
5885         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5886                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5887
5888         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5889                             &parent_dir_src, NULL) ||
5890             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5891                             &parent_dir_dst, NULL)) {
5892                 goto out;
5893         }
5894
5895         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5896                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5897                              smb_fname_src->base_name);
5898                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5899                              smb_fname_dst->base_name);
5900         }
5901         else {
5902                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5903                              smb_fname_src->base_name);
5904                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5905                              smb_fname_dst->base_name);
5906         }
5907
5908         /* this is a strange one. w2k3 gives an additional event for
5909            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5910            files, but not directories */
5911         if (!is_dir) {
5912                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5913                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5914                              |FILE_NOTIFY_CHANGE_CREATION,
5915                              smb_fname_dst->base_name);
5916         }
5917  out:
5918         TALLOC_FREE(parent_dir_src);
5919         TALLOC_FREE(parent_dir_dst);
5920 }
5921
5922 /****************************************************************************
5923  Rename an open file - given an fsp.
5924 ****************************************************************************/
5925
5926 NTSTATUS rename_internals_fsp(connection_struct *conn,
5927                         files_struct *fsp,
5928                         const struct smb_filename *smb_fname_dst_in,
5929                         uint32 attrs,
5930                         bool replace_if_exists)
5931 {
5932         TALLOC_CTX *ctx = talloc_tos();
5933         struct smb_filename *smb_fname_dst = NULL;
5934         NTSTATUS status = NT_STATUS_OK;
5935         struct share_mode_lock *lck = NULL;
5936         bool dst_exists, old_is_stream, new_is_stream;
5937
5938         status = check_name(conn, smb_fname_dst_in->base_name);
5939         if (!NT_STATUS_IS_OK(status)) {
5940                 return status;
5941         }
5942
5943         /* Make a copy of the dst smb_fname structs */
5944
5945         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5946         if (!NT_STATUS_IS_OK(status)) {
5947                 goto out;
5948         }
5949
5950         /*
5951          * Check for special case with case preserving and not
5952          * case sensitive. If the old last component differs from the original
5953          * last component only by case, then we should allow
5954          * the rename (user is trying to change the case of the
5955          * filename).
5956          */
5957         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5958             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5959             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5960                 char *last_slash;
5961                 char *fname_dst_lcomp_base_mod = NULL;
5962                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5963
5964                 /*
5965                  * Get the last component of the destination name.
5966                  */
5967                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5968                 if (last_slash) {
5969                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5970                 } else {
5971                         fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5972                 }
5973                 if (!fname_dst_lcomp_base_mod) {
5974                         status = NT_STATUS_NO_MEMORY;
5975                         goto out;
5976                 }
5977
5978                 /*
5979                  * Create an smb_filename struct using the original last
5980                  * component of the destination.
5981                  */
5982                 status = create_synthetic_smb_fname_split(ctx,
5983                     smb_fname_dst->original_lcomp, NULL,
5984                     &smb_fname_orig_lcomp);
5985                 if (!NT_STATUS_IS_OK(status)) {
5986                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5987                         goto out;
5988                 }
5989
5990                 /* If the base names only differ by case, use original. */
5991                 if(!strcsequal(fname_dst_lcomp_base_mod,
5992                                smb_fname_orig_lcomp->base_name)) {
5993                         char *tmp;
5994                         /*
5995                          * Replace the modified last component with the
5996                          * original.
5997                          */
5998                         if (last_slash) {
5999                                 *last_slash = '\0'; /* Truncate at the '/' */
6000                                 tmp = talloc_asprintf(smb_fname_dst,
6001                                         "%s/%s",
6002                                         smb_fname_dst->base_name,
6003                                         smb_fname_orig_lcomp->base_name);
6004                         } else {
6005                                 tmp = talloc_asprintf(smb_fname_dst,
6006                                         "%s",
6007                                         smb_fname_orig_lcomp->base_name);
6008                         }
6009                         if (tmp == NULL) {
6010                                 status = NT_STATUS_NO_MEMORY;
6011                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6012                                 TALLOC_FREE(smb_fname_orig_lcomp);
6013                                 goto out;
6014                         }
6015                         TALLOC_FREE(smb_fname_dst->base_name);
6016                         smb_fname_dst->base_name = tmp;
6017                 }
6018
6019                 /* If the stream_names only differ by case, use original. */
6020                 if(!strcsequal(smb_fname_dst->stream_name,
6021                                smb_fname_orig_lcomp->stream_name)) {
6022                         char *tmp = NULL;
6023                         /* Use the original stream. */
6024                         tmp = talloc_strdup(smb_fname_dst,
6025                                             smb_fname_orig_lcomp->stream_name);
6026                         if (tmp == NULL) {
6027                                 status = NT_STATUS_NO_MEMORY;
6028                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6029                                 TALLOC_FREE(smb_fname_orig_lcomp);
6030                                 goto out;
6031                         }
6032                         TALLOC_FREE(smb_fname_dst->stream_name);
6033                         smb_fname_dst->stream_name = tmp;
6034                 }
6035                 TALLOC_FREE(fname_dst_lcomp_base_mod);
6036                 TALLOC_FREE(smb_fname_orig_lcomp);
6037         }
6038
6039         /*
6040          * If the src and dest names are identical - including case,
6041          * don't do the rename, just return success.
6042          */
6043
6044         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6045             strcsequal(fsp->fsp_name->stream_name,
6046                        smb_fname_dst->stream_name)) {
6047                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6048                           "- returning success\n",
6049                           smb_fname_str_dbg(smb_fname_dst)));
6050                 status = NT_STATUS_OK;
6051                 goto out;
6052         }
6053
6054         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6055         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6056
6057         /* Return the correct error code if both names aren't streams. */
6058         if (!old_is_stream && new_is_stream) {
6059                 status = NT_STATUS_OBJECT_NAME_INVALID;
6060                 goto out;
6061         }
6062
6063         if (old_is_stream && !new_is_stream) {
6064                 status = NT_STATUS_INVALID_PARAMETER;
6065                 goto out;
6066         }
6067
6068         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6069
6070         if(!replace_if_exists && dst_exists) {
6071                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6072                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6073                           smb_fname_str_dbg(smb_fname_dst)));
6074                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6075                 goto out;
6076         }
6077
6078         if (dst_exists) {
6079                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6080                     &smb_fname_dst->st);
6081                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6082                                                            fileid);
6083                 /* The file can be open when renaming a stream */
6084                 if (dst_fsp && !new_is_stream) {
6085                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6086                         status = NT_STATUS_ACCESS_DENIED;
6087                         goto out;
6088                 }
6089         }
6090
6091         /* Ensure we have a valid stat struct for the source. */
6092         status = vfs_stat_fsp(fsp);
6093         if (!NT_STATUS_IS_OK(status)) {
6094                 goto out;
6095         }
6096
6097         status = can_rename(conn, fsp, attrs);
6098
6099         if (!NT_STATUS_IS_OK(status)) {
6100                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6101                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6102                           smb_fname_str_dbg(smb_fname_dst)));
6103                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6104                         status = NT_STATUS_ACCESS_DENIED;
6105                 goto out;
6106         }
6107
6108         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6109                 status = NT_STATUS_ACCESS_DENIED;
6110         }
6111
6112         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6113                                   NULL);
6114
6115         /*
6116          * We have the file open ourselves, so not being able to get the
6117          * corresponding share mode lock is a fatal error.
6118          */
6119
6120         SMB_ASSERT(lck != NULL);
6121
6122         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6123                 uint32 create_options = fsp->fh->private_options;
6124
6125                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6126                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6127                           smb_fname_str_dbg(smb_fname_dst)));
6128
6129                 if (!lp_posix_pathnames() &&
6130                     (lp_map_archive(SNUM(conn)) ||
6131                     lp_store_dos_attributes(SNUM(conn)))) {
6132                         /* We must set the archive bit on the newly
6133                            renamed file. */
6134                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6135                                 uint32_t old_dosmode = dos_mode(conn,
6136                                                         smb_fname_dst);
6137                                 file_set_dosmode(conn,
6138                                         smb_fname_dst,
6139                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6140                                         NULL,
6141                                         true);
6142                         }
6143                 }
6144
6145                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6146                               smb_fname_dst);
6147
6148                 rename_open_files(conn, lck, smb_fname_dst);
6149
6150                 /*
6151                  * A rename acts as a new file create w.r.t. allowing an initial delete
6152                  * on close, probably because in Windows there is a new handle to the
6153                  * new file. If initial delete on close was requested but not
6154                  * originally set, we need to set it here. This is probably not 100% correct,
6155                  * but will work for the CIFSFS client which in non-posix mode
6156                  * depends on these semantics. JRA.
6157                  */
6158
6159                 if (create_options & FILE_DELETE_ON_CLOSE) {
6160                         status = can_set_delete_on_close(fsp, 0);
6161
6162                         if (NT_STATUS_IS_OK(status)) {
6163                                 /* Note that here we set the *inital* delete on close flag,
6164                                  * not the regular one. The magic gets handled in close. */
6165                                 fsp->initial_delete_on_close = True;
6166                         }
6167                 }
6168                 TALLOC_FREE(lck);
6169                 status = NT_STATUS_OK;
6170                 goto out;
6171         }
6172
6173         TALLOC_FREE(lck);
6174
6175         if (errno == ENOTDIR || errno == EISDIR) {
6176                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6177         } else {
6178                 status = map_nt_error_from_unix(errno);
6179         }
6180
6181         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6182                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6183                   smb_fname_str_dbg(smb_fname_dst)));
6184
6185  out:
6186         TALLOC_FREE(smb_fname_dst);
6187
6188         return status;
6189 }
6190
6191 /****************************************************************************
6192  The guts of the rename command, split out so it may be called by the NT SMB
6193  code.
6194 ****************************************************************************/
6195
6196 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6197                         connection_struct *conn,
6198                         struct smb_request *req,
6199                         struct smb_filename *smb_fname_src,
6200                         struct smb_filename *smb_fname_dst,
6201                         uint32 attrs,
6202                         bool replace_if_exists,
6203                         bool src_has_wild,
6204                         bool dest_has_wild,
6205                         uint32_t access_mask)
6206 {
6207         char *fname_src_dir = NULL;
6208         char *fname_src_mask = NULL;
6209         int count=0;
6210         NTSTATUS status = NT_STATUS_OK;
6211         struct smb_Dir *dir_hnd = NULL;
6212         const char *dname = NULL;
6213         char *talloced = NULL;
6214         long offset = 0;
6215         int create_options = 0;
6216         bool posix_pathnames = lp_posix_pathnames();
6217
6218         /*
6219          * Split the old name into directory and last component
6220          * strings. Note that unix_convert may have stripped off a
6221          * leading ./ from both name and newname if the rename is
6222          * at the root of the share. We need to make sure either both
6223          * name and newname contain a / character or neither of them do
6224          * as this is checked in resolve_wildcards().
6225          */
6226
6227         /* Split up the directory from the filename/mask. */
6228         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6229                                       &fname_src_dir, &fname_src_mask);
6230         if (!NT_STATUS_IS_OK(status)) {
6231                 status = NT_STATUS_NO_MEMORY;
6232                 goto out;
6233         }
6234
6235         /*
6236          * We should only check the mangled cache
6237          * here if unix_convert failed. This means
6238          * that the path in 'mask' doesn't exist
6239          * on the file system and so we need to look
6240          * for a possible mangle. This patch from
6241          * Tine Smukavec <valentin.smukavec@hermes.si>.
6242          */
6243
6244         if (!VALID_STAT(smb_fname_src->st) &&
6245             mangle_is_mangled(fname_src_mask, conn->params)) {
6246                 char *new_mask = NULL;
6247                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6248                                             conn->params);
6249                 if (new_mask) {
6250                         TALLOC_FREE(fname_src_mask);
6251                         fname_src_mask = new_mask;
6252                 }
6253         }
6254
6255         if (!src_has_wild) {
6256                 files_struct *fsp;
6257
6258                 /*
6259                  * Only one file needs to be renamed. Append the mask back
6260                  * onto the directory.
6261                  */
6262                 TALLOC_FREE(smb_fname_src->base_name);
6263                 if (ISDOT(fname_src_dir)) {
6264                         /* Ensure we use canonical names on open. */
6265                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6266                                                         "%s",
6267                                                         fname_src_mask);
6268                 } else {
6269                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6270                                                         "%s/%s",
6271                                                         fname_src_dir,
6272                                                         fname_src_mask);
6273                 }
6274                 if (!smb_fname_src->base_name) {
6275                         status = NT_STATUS_NO_MEMORY;
6276                         goto out;
6277                 }
6278
6279                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6280                           "case_preserve = %d, short case preserve = %d, "
6281                           "directory = %s, newname = %s, "
6282                           "last_component_dest = %s\n",
6283                           conn->case_sensitive, conn->case_preserve,
6284                           conn->short_case_preserve,
6285                           smb_fname_str_dbg(smb_fname_src),
6286                           smb_fname_str_dbg(smb_fname_dst),
6287                           smb_fname_dst->original_lcomp));
6288
6289                 /* The dest name still may have wildcards. */
6290                 if (dest_has_wild) {
6291                         char *fname_dst_mod = NULL;
6292                         if (!resolve_wildcards(smb_fname_dst,
6293                                                smb_fname_src->base_name,
6294                                                smb_fname_dst->base_name,
6295                                                &fname_dst_mod)) {
6296                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6297                                           "%s %s failed\n",
6298                                           smb_fname_src->base_name,
6299                                           smb_fname_dst->base_name));
6300                                 status = NT_STATUS_NO_MEMORY;
6301                                 goto out;
6302                         }
6303                         TALLOC_FREE(smb_fname_dst->base_name);
6304                         smb_fname_dst->base_name = fname_dst_mod;
6305                 }
6306
6307                 ZERO_STRUCT(smb_fname_src->st);
6308                 if (posix_pathnames) {
6309                         SMB_VFS_LSTAT(conn, smb_fname_src);
6310                 } else {
6311                         SMB_VFS_STAT(conn, smb_fname_src);
6312                 }
6313
6314                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6315                         create_options |= FILE_DIRECTORY_FILE;
6316                 }
6317
6318                 status = SMB_VFS_CREATE_FILE(
6319                         conn,                           /* conn */
6320                         req,                            /* req */
6321                         0,                              /* root_dir_fid */
6322                         smb_fname_src,                  /* fname */
6323                         access_mask,                    /* access_mask */
6324                         (FILE_SHARE_READ |              /* share_access */
6325                             FILE_SHARE_WRITE),
6326                         FILE_OPEN,                      /* create_disposition*/
6327                         create_options,                 /* create_options */
6328                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6329                         0,                              /* oplock_request */
6330                         0,                              /* allocation_size */
6331                         0,                              /* private_flags */
6332                         NULL,                           /* sd */
6333                         NULL,                           /* ea_list */
6334                         &fsp,                           /* result */
6335                         NULL);                          /* pinfo */
6336
6337                 if (!NT_STATUS_IS_OK(status)) {
6338                         DEBUG(3, ("Could not open rename source %s: %s\n",
6339                                   smb_fname_str_dbg(smb_fname_src),
6340                                   nt_errstr(status)));
6341                         goto out;
6342                 }
6343
6344                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6345                                               attrs, replace_if_exists);
6346
6347                 close_file(req, fsp, NORMAL_CLOSE);
6348
6349                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6350                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6351                           smb_fname_str_dbg(smb_fname_dst)));
6352
6353                 goto out;
6354         }
6355
6356         /*
6357          * Wildcards - process each file that matches.
6358          */
6359         if (strequal(fname_src_mask, "????????.???")) {
6360                 TALLOC_FREE(fname_src_mask);
6361                 fname_src_mask = talloc_strdup(ctx, "*");
6362                 if (!fname_src_mask) {
6363                         status = NT_STATUS_NO_MEMORY;
6364                         goto out;
6365                 }
6366         }
6367
6368         status = check_name(conn, fname_src_dir);
6369         if (!NT_STATUS_IS_OK(status)) {
6370                 goto out;
6371         }
6372
6373         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6374                           attrs);
6375         if (dir_hnd == NULL) {
6376                 status = map_nt_error_from_unix(errno);
6377                 goto out;
6378         }
6379
6380         status = NT_STATUS_NO_SUCH_FILE;
6381         /*
6382          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6383          * - gentest fix. JRA
6384          */
6385
6386         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6387                                     &talloced))) {
6388                 files_struct *fsp = NULL;
6389                 char *destname = NULL;
6390                 bool sysdir_entry = False;
6391
6392                 /* Quick check for "." and ".." */
6393                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6394                         if (attrs & aDIR) {
6395                                 sysdir_entry = True;
6396                         } else {
6397                                 TALLOC_FREE(talloced);
6398                                 continue;
6399                         }
6400                 }
6401
6402                 if (!is_visible_file(conn, fname_src_dir, dname,
6403                                      &smb_fname_src->st, false)) {
6404                         TALLOC_FREE(talloced);
6405                         continue;
6406                 }
6407
6408                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6409                         TALLOC_FREE(talloced);
6410                         continue;
6411                 }
6412
6413                 if (sysdir_entry) {
6414                         status = NT_STATUS_OBJECT_NAME_INVALID;
6415                         break;
6416                 }
6417
6418                 TALLOC_FREE(smb_fname_src->base_name);
6419                 if (ISDOT(fname_src_dir)) {
6420                         /* Ensure we use canonical names on open. */
6421                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6422                                                         "%s",
6423                                                         dname);
6424                 } else {
6425                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6426                                                         "%s/%s",
6427                                                         fname_src_dir,
6428                                                         dname);
6429                 }
6430                 if (!smb_fname_src->base_name) {
6431                         status = NT_STATUS_NO_MEMORY;
6432                         goto out;
6433                 }
6434
6435                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6436                                        smb_fname_dst->base_name,
6437                                        &destname)) {
6438                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6439                                   smb_fname_src->base_name, destname));
6440                         TALLOC_FREE(talloced);
6441                         continue;
6442                 }
6443                 if (!destname) {
6444                         status = NT_STATUS_NO_MEMORY;
6445                         goto out;
6446                 }
6447
6448                 TALLOC_FREE(smb_fname_dst->base_name);
6449                 smb_fname_dst->base_name = destname;
6450
6451                 ZERO_STRUCT(smb_fname_src->st);
6452                 if (posix_pathnames) {
6453                         SMB_VFS_LSTAT(conn, smb_fname_src);
6454                 } else {
6455                         SMB_VFS_STAT(conn, smb_fname_src);
6456                 }
6457
6458                 create_options = 0;
6459
6460                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6461                         create_options |= FILE_DIRECTORY_FILE;
6462                 }
6463
6464                 status = SMB_VFS_CREATE_FILE(
6465                         conn,                           /* conn */
6466                         req,                            /* req */
6467                         0,                              /* root_dir_fid */
6468                         smb_fname_src,                  /* fname */
6469                         access_mask,                    /* access_mask */
6470                         (FILE_SHARE_READ |              /* share_access */
6471                             FILE_SHARE_WRITE),
6472                         FILE_OPEN,                      /* create_disposition*/
6473                         create_options,                 /* create_options */
6474                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6475                         0,                              /* oplock_request */
6476                         0,                              /* allocation_size */
6477                         0,                              /* private_flags */
6478                         NULL,                           /* sd */
6479                         NULL,                           /* ea_list */
6480                         &fsp,                           /* result */
6481                         NULL);                          /* pinfo */
6482
6483                 if (!NT_STATUS_IS_OK(status)) {
6484                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6485                                  "returned %s rename %s -> %s\n",
6486                                  nt_errstr(status),
6487                                  smb_fname_str_dbg(smb_fname_src),
6488                                  smb_fname_str_dbg(smb_fname_dst)));
6489                         break;
6490                 }
6491
6492                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6493                                                               dname);
6494                 if (!smb_fname_dst->original_lcomp) {
6495                         status = NT_STATUS_NO_MEMORY;
6496                         goto out;
6497                 }
6498
6499                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6500                                               attrs, replace_if_exists);
6501
6502                 close_file(req, fsp, NORMAL_CLOSE);
6503
6504                 if (!NT_STATUS_IS_OK(status)) {
6505                         DEBUG(3, ("rename_internals_fsp returned %s for "
6506                                   "rename %s -> %s\n", nt_errstr(status),
6507                                   smb_fname_str_dbg(smb_fname_src),
6508                                   smb_fname_str_dbg(smb_fname_dst)));
6509                         break;
6510                 }
6511
6512                 count++;
6513
6514                 DEBUG(3,("rename_internals: doing rename on %s -> "
6515                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6516                          smb_fname_str_dbg(smb_fname_src)));
6517                 TALLOC_FREE(talloced);
6518         }
6519         TALLOC_FREE(dir_hnd);
6520
6521         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6522                 status = map_nt_error_from_unix(errno);
6523         }
6524
6525  out:
6526         TALLOC_FREE(talloced);
6527         TALLOC_FREE(fname_src_dir);
6528         TALLOC_FREE(fname_src_mask);
6529         return status;
6530 }
6531
6532 /****************************************************************************
6533  Reply to a mv.
6534 ****************************************************************************/
6535
6536 void reply_mv(struct smb_request *req)
6537 {
6538         connection_struct *conn = req->conn;
6539         char *name = NULL;
6540         char *newname = NULL;
6541         const char *p;
6542         uint32 attrs;
6543         NTSTATUS status;
6544         bool src_has_wcard = False;
6545         bool dest_has_wcard = False;
6546         TALLOC_CTX *ctx = talloc_tos();
6547         struct smb_filename *smb_fname_src = NULL;
6548         struct smb_filename *smb_fname_dst = NULL;
6549         bool stream_rename = false;
6550
6551         START_PROFILE(SMBmv);
6552
6553         if (req->wct < 1) {
6554                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6555                 goto out;
6556         }
6557
6558         attrs = SVAL(req->vwv+0, 0);
6559
6560         p = (const char *)req->buf + 1;
6561         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6562                                        &status, &src_has_wcard);
6563         if (!NT_STATUS_IS_OK(status)) {
6564                 reply_nterror(req, status);
6565                 goto out;
6566         }
6567         p++;
6568         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6569                                        &status, &dest_has_wcard);
6570         if (!NT_STATUS_IS_OK(status)) {
6571                 reply_nterror(req, status);
6572                 goto out;
6573         }
6574
6575         if (!lp_posix_pathnames()) {
6576                 /* The newname must begin with a ':' if the
6577                    name contains a ':'. */
6578                 if (strchr_m(name, ':')) {
6579                         if (newname[0] != ':') {
6580                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6581                                 goto out;
6582                         }
6583                         stream_rename = true;
6584                 }
6585         }
6586
6587         status = filename_convert(ctx,
6588                                   conn,
6589                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6590                                   name,
6591                                   UCF_COND_ALLOW_WCARD_LCOMP,
6592                                   &src_has_wcard,
6593                                   &smb_fname_src);
6594
6595         if (!NT_STATUS_IS_OK(status)) {
6596                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6597                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6598                                         ERRSRV, ERRbadpath);
6599                         goto out;
6600                 }
6601                 reply_nterror(req, status);
6602                 goto out;
6603         }
6604
6605         status = filename_convert(ctx,
6606                                   conn,
6607                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6608                                   newname,
6609                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6610                                   &dest_has_wcard,
6611                                   &smb_fname_dst);
6612
6613         if (!NT_STATUS_IS_OK(status)) {
6614                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6615                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6616                                         ERRSRV, ERRbadpath);
6617                         goto out;
6618                 }
6619                 reply_nterror(req, status);
6620                 goto out;
6621         }
6622
6623         if (stream_rename) {
6624                 /* smb_fname_dst->base_name must be the same as
6625                    smb_fname_src->base_name. */
6626                 TALLOC_FREE(smb_fname_dst->base_name);
6627                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6628                                                 smb_fname_src->base_name);
6629                 if (!smb_fname_dst->base_name) {
6630                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6631                         goto out;
6632                 }
6633         }
6634
6635         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6636                  smb_fname_str_dbg(smb_fname_dst)));
6637
6638         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6639                                   attrs, False, src_has_wcard, dest_has_wcard,
6640                                   DELETE_ACCESS);
6641         if (!NT_STATUS_IS_OK(status)) {
6642                 if (open_was_deferred(req->mid)) {
6643                         /* We have re-scheduled this call. */
6644                         goto out;
6645                 }
6646                 reply_nterror(req, status);
6647                 goto out;
6648         }
6649
6650         reply_outbuf(req, 0, 0);
6651  out:
6652         TALLOC_FREE(smb_fname_src);
6653         TALLOC_FREE(smb_fname_dst);
6654         END_PROFILE(SMBmv);
6655         return;
6656 }
6657
6658 /*******************************************************************
6659  Copy a file as part of a reply_copy.
6660 ******************************************************************/
6661
6662 /*
6663  * TODO: check error codes on all callers
6664  */
6665
6666 NTSTATUS copy_file(TALLOC_CTX *ctx,
6667                         connection_struct *conn,
6668                         struct smb_filename *smb_fname_src,
6669                         struct smb_filename *smb_fname_dst,
6670                         int ofun,
6671                         int count,
6672                         bool target_is_directory)
6673 {
6674         struct smb_filename *smb_fname_dst_tmp = NULL;
6675         SMB_OFF_T ret=-1;
6676         files_struct *fsp1,*fsp2;
6677         uint32 dosattrs;
6678         uint32 new_create_disposition;
6679         NTSTATUS status;
6680
6681
6682         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6683         if (!NT_STATUS_IS_OK(status)) {
6684                 return status;
6685         }
6686
6687         /*
6688          * If the target is a directory, extract the last component from the
6689          * src filename and append it to the dst filename
6690          */
6691         if (target_is_directory) {
6692                 const char *p;
6693
6694                 /* dest/target can't be a stream if it's a directory. */
6695                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6696
6697                 p = strrchr_m(smb_fname_src->base_name,'/');
6698                 if (p) {
6699                         p++;
6700                 } else {
6701                         p = smb_fname_src->base_name;
6702                 }
6703                 smb_fname_dst_tmp->base_name =
6704                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6705                                            p);
6706                 if (!smb_fname_dst_tmp->base_name) {
6707                         status = NT_STATUS_NO_MEMORY;
6708                         goto out;
6709                 }
6710         }
6711
6712         status = vfs_file_exist(conn, smb_fname_src);
6713         if (!NT_STATUS_IS_OK(status)) {
6714                 goto out;
6715         }
6716
6717         if (!target_is_directory && count) {
6718                 new_create_disposition = FILE_OPEN;
6719         } else {
6720                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6721                                                  NULL, NULL,
6722                                                  &new_create_disposition,
6723                                                  NULL,
6724                                                  NULL)) {
6725                         status = NT_STATUS_INVALID_PARAMETER;
6726                         goto out;
6727                 }
6728         }
6729
6730         /* Open the src file for reading. */
6731         status = SMB_VFS_CREATE_FILE(
6732                 conn,                                   /* conn */
6733                 NULL,                                   /* req */
6734                 0,                                      /* root_dir_fid */
6735                 smb_fname_src,                          /* fname */
6736                 FILE_GENERIC_READ,                      /* access_mask */
6737                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6738                 FILE_OPEN,                              /* create_disposition*/
6739                 0,                                      /* create_options */
6740                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6741                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6742                 0,                                      /* allocation_size */
6743                 0,                                      /* private_flags */
6744                 NULL,                                   /* sd */
6745                 NULL,                                   /* ea_list */
6746                 &fsp1,                                  /* result */
6747                 NULL);                                  /* psbuf */
6748
6749         if (!NT_STATUS_IS_OK(status)) {
6750                 goto out;
6751         }
6752
6753         dosattrs = dos_mode(conn, smb_fname_src);
6754
6755         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6756                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6757         }
6758
6759         /* Open the dst file for writing. */
6760         status = SMB_VFS_CREATE_FILE(
6761                 conn,                                   /* conn */
6762                 NULL,                                   /* req */
6763                 0,                                      /* root_dir_fid */
6764                 smb_fname_dst,                          /* fname */
6765                 FILE_GENERIC_WRITE,                     /* access_mask */
6766                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6767                 new_create_disposition,                 /* create_disposition*/
6768                 0,                                      /* create_options */
6769                 dosattrs,                               /* file_attributes */
6770                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6771                 0,                                      /* allocation_size */
6772                 0,                                      /* private_flags */
6773                 NULL,                                   /* sd */
6774                 NULL,                                   /* ea_list */
6775                 &fsp2,                                  /* result */
6776                 NULL);                                  /* psbuf */
6777
6778         if (!NT_STATUS_IS_OK(status)) {
6779                 close_file(NULL, fsp1, ERROR_CLOSE);
6780                 goto out;
6781         }
6782
6783         if ((ofun&3) == 1) {
6784                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6785                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6786                         /*
6787                          * Stop the copy from occurring.
6788                          */
6789                         ret = -1;
6790                         smb_fname_src->st.st_ex_size = 0;
6791                 }
6792         }
6793
6794         /* Do the actual copy. */
6795         if (smb_fname_src->st.st_ex_size) {
6796                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6797         }
6798
6799         close_file(NULL, fsp1, NORMAL_CLOSE);
6800
6801         /* Ensure the modtime is set correctly on the destination file. */
6802         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6803
6804         /*
6805          * As we are opening fsp1 read-only we only expect
6806          * an error on close on fsp2 if we are out of space.
6807          * Thus we don't look at the error return from the
6808          * close of fsp1.
6809          */
6810         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6811
6812         if (!NT_STATUS_IS_OK(status)) {
6813                 goto out;
6814         }
6815
6816         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6817                 status = NT_STATUS_DISK_FULL;
6818                 goto out;
6819         }
6820
6821         status = NT_STATUS_OK;
6822
6823  out:
6824         TALLOC_FREE(smb_fname_dst_tmp);
6825         return status;
6826 }
6827
6828 /****************************************************************************
6829  Reply to a file copy.
6830 ****************************************************************************/
6831
6832 void reply_copy(struct smb_request *req)
6833 {
6834         connection_struct *conn = req->conn;
6835         struct smb_filename *smb_fname_src = NULL;
6836         struct smb_filename *smb_fname_dst = NULL;
6837         char *fname_src = NULL;
6838         char *fname_dst = NULL;
6839         char *fname_src_mask = NULL;
6840         char *fname_src_dir = NULL;
6841         const char *p;
6842         int count=0;
6843         int error = ERRnoaccess;
6844         int tid2;
6845         int ofun;
6846         int flags;
6847         bool target_is_directory=False;
6848         bool source_has_wild = False;
6849         bool dest_has_wild = False;
6850         NTSTATUS status;
6851         TALLOC_CTX *ctx = talloc_tos();
6852
6853         START_PROFILE(SMBcopy);
6854
6855         if (req->wct < 3) {
6856                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6857                 goto out;
6858         }
6859
6860         tid2 = SVAL(req->vwv+0, 0);
6861         ofun = SVAL(req->vwv+1, 0);
6862         flags = SVAL(req->vwv+2, 0);
6863
6864         p = (const char *)req->buf;
6865         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6866                                        &status, &source_has_wild);
6867         if (!NT_STATUS_IS_OK(status)) {
6868                 reply_nterror(req, status);
6869                 goto out;
6870         }
6871         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6872                                        &status, &dest_has_wild);
6873         if (!NT_STATUS_IS_OK(status)) {
6874                 reply_nterror(req, status);
6875                 goto out;
6876         }
6877
6878         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6879
6880         if (tid2 != conn->cnum) {
6881                 /* can't currently handle inter share copies XXXX */
6882                 DEBUG(3,("Rejecting inter-share copy\n"));
6883                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6884                 goto out;
6885         }
6886
6887         status = filename_convert(ctx, conn,
6888                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6889                                   fname_src,
6890                                   UCF_COND_ALLOW_WCARD_LCOMP,
6891                                   &source_has_wild,
6892                                   &smb_fname_src);
6893         if (!NT_STATUS_IS_OK(status)) {
6894                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6895                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6896                                         ERRSRV, ERRbadpath);
6897                         goto out;
6898                 }
6899                 reply_nterror(req, status);
6900                 goto out;
6901         }
6902
6903         status = filename_convert(ctx, conn,
6904                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6905                                   fname_dst,
6906                                   UCF_COND_ALLOW_WCARD_LCOMP,
6907                                   &dest_has_wild,
6908                                   &smb_fname_dst);
6909         if (!NT_STATUS_IS_OK(status)) {
6910                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6911                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6912                                         ERRSRV, ERRbadpath);
6913                         goto out;
6914                 }
6915                 reply_nterror(req, status);
6916                 goto out;
6917         }
6918
6919         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6920
6921         if ((flags&1) && target_is_directory) {
6922                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6923                 goto out;
6924         }
6925
6926         if ((flags&2) && !target_is_directory) {
6927                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6928                 goto out;
6929         }
6930
6931         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6932                 /* wants a tree copy! XXXX */
6933                 DEBUG(3,("Rejecting tree copy\n"));
6934                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6935                 goto out;
6936         }
6937
6938         /* Split up the directory from the filename/mask. */
6939         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6940                                       &fname_src_dir, &fname_src_mask);
6941         if (!NT_STATUS_IS_OK(status)) {
6942                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6943                 goto out;
6944         }
6945
6946         /*
6947          * We should only check the mangled cache
6948          * here if unix_convert failed. This means
6949          * that the path in 'mask' doesn't exist
6950          * on the file system and so we need to look
6951          * for a possible mangle. This patch from
6952          * Tine Smukavec <valentin.smukavec@hermes.si>.
6953          */
6954         if (!VALID_STAT(smb_fname_src->st) &&
6955             mangle_is_mangled(fname_src_mask, conn->params)) {
6956                 char *new_mask = NULL;
6957                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6958                                             &new_mask, conn->params);
6959
6960                 /* Use demangled name if one was successfully found. */
6961                 if (new_mask) {
6962                         TALLOC_FREE(fname_src_mask);
6963                         fname_src_mask = new_mask;
6964                 }
6965         }
6966
6967         if (!source_has_wild) {
6968
6969                 /*
6970                  * Only one file needs to be copied. Append the mask back onto
6971                  * the directory.
6972                  */
6973                 TALLOC_FREE(smb_fname_src->base_name);
6974                 if (ISDOT(fname_src_dir)) {
6975                         /* Ensure we use canonical names on open. */
6976                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6977                                                         "%s",
6978                                                         fname_src_mask);
6979                 } else {
6980                         smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6981                                                         "%s/%s",
6982                                                         fname_src_dir,
6983                                                         fname_src_mask);
6984                 }
6985                 if (!smb_fname_src->base_name) {
6986                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6987                         goto out;
6988                 }
6989
6990                 if (dest_has_wild) {
6991                         char *fname_dst_mod = NULL;
6992                         if (!resolve_wildcards(smb_fname_dst,
6993                                                smb_fname_src->base_name,
6994                                                smb_fname_dst->base_name,
6995                                                &fname_dst_mod)) {
6996                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6997                                 goto out;
6998                         }
6999                         TALLOC_FREE(smb_fname_dst->base_name);
7000                         smb_fname_dst->base_name = fname_dst_mod;
7001                 }
7002
7003                 status = check_name(conn, smb_fname_src->base_name);
7004                 if (!NT_STATUS_IS_OK(status)) {
7005                         reply_nterror(req, status);
7006                         goto out;
7007                 }
7008
7009                 status = check_name(conn, smb_fname_dst->base_name);
7010                 if (!NT_STATUS_IS_OK(status)) {
7011                         reply_nterror(req, status);
7012                         goto out;
7013                 }
7014
7015                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7016                                    ofun, count, target_is_directory);
7017
7018                 if(!NT_STATUS_IS_OK(status)) {
7019                         reply_nterror(req, status);
7020                         goto out;
7021                 } else {
7022                         count++;
7023                 }
7024         } else {
7025                 struct smb_Dir *dir_hnd = NULL;
7026                 const char *dname = NULL;
7027                 char *talloced = NULL;
7028                 long offset = 0;
7029
7030                 /*
7031                  * There is a wildcard that requires us to actually read the
7032                  * src dir and copy each file matching the mask to the dst.
7033                  * Right now streams won't be copied, but this could
7034                  * presumably be added with a nested loop for reach dir entry.
7035                  */
7036                 SMB_ASSERT(!smb_fname_src->stream_name);
7037                 SMB_ASSERT(!smb_fname_dst->stream_name);
7038
7039                 smb_fname_src->stream_name = NULL;
7040                 smb_fname_dst->stream_name = NULL;
7041
7042                 if (strequal(fname_src_mask,"????????.???")) {
7043                         TALLOC_FREE(fname_src_mask);
7044                         fname_src_mask = talloc_strdup(ctx, "*");
7045                         if (!fname_src_mask) {
7046                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7047                                 goto out;
7048                         }
7049                 }
7050
7051                 status = check_name(conn, fname_src_dir);
7052                 if (!NT_STATUS_IS_OK(status)) {
7053                         reply_nterror(req, status);
7054                         goto out;
7055                 }
7056
7057                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7058                 if (dir_hnd == NULL) {
7059                         status = map_nt_error_from_unix(errno);
7060                         reply_nterror(req, status);
7061                         goto out;
7062                 }
7063
7064                 error = ERRbadfile;
7065
7066                 /* Iterate over the src dir copying each entry to the dst. */
7067                 while ((dname = ReadDirName(dir_hnd, &offset,
7068                                             &smb_fname_src->st, &talloced))) {
7069                         char *destname = NULL;
7070
7071                         if (ISDOT(dname) || ISDOTDOT(dname)) {
7072                                 TALLOC_FREE(talloced);
7073                                 continue;
7074                         }
7075
7076                         if (!is_visible_file(conn, fname_src_dir, dname,
7077                                              &smb_fname_src->st, false)) {
7078                                 TALLOC_FREE(talloced);
7079                                 continue;
7080                         }
7081
7082                         if(!mask_match(dname, fname_src_mask,
7083                                        conn->case_sensitive)) {
7084                                 TALLOC_FREE(talloced);
7085                                 continue;
7086                         }
7087
7088                         error = ERRnoaccess;
7089
7090                         /* Get the src smb_fname struct setup. */
7091                         TALLOC_FREE(smb_fname_src->base_name);
7092                         if (ISDOT(fname_src_dir)) {
7093                                 /* Ensure we use canonical names on open. */
7094                                 smb_fname_src->base_name =
7095                                         talloc_asprintf(smb_fname_src, "%s",
7096                                                 dname);
7097                         } else {
7098                                 smb_fname_src->base_name =
7099                                         talloc_asprintf(smb_fname_src, "%s/%s",
7100                                                 fname_src_dir, dname);
7101                         }
7102
7103                         if (!smb_fname_src->base_name) {
7104                                 TALLOC_FREE(dir_hnd);
7105                                 TALLOC_FREE(talloced);
7106                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7107                                 goto out;
7108                         }
7109
7110                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7111                                                smb_fname_dst->base_name,
7112                                                &destname)) {
7113                                 TALLOC_FREE(talloced);
7114                                 continue;
7115                         }
7116                         if (!destname) {
7117                                 TALLOC_FREE(dir_hnd);
7118                                 TALLOC_FREE(talloced);
7119                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7120                                 goto out;
7121                         }
7122
7123                         TALLOC_FREE(smb_fname_dst->base_name);
7124                         smb_fname_dst->base_name = destname;
7125
7126                         status = check_name(conn, smb_fname_src->base_name);
7127                         if (!NT_STATUS_IS_OK(status)) {
7128                                 TALLOC_FREE(dir_hnd);
7129                                 TALLOC_FREE(talloced);
7130                                 reply_nterror(req, status);
7131                                 goto out;
7132                         }
7133
7134                         status = check_name(conn, smb_fname_dst->base_name);
7135                         if (!NT_STATUS_IS_OK(status)) {
7136                                 TALLOC_FREE(dir_hnd);
7137                                 TALLOC_FREE(talloced);
7138                                 reply_nterror(req, status);
7139                                 goto out;
7140                         }
7141
7142                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7143                                 smb_fname_src->base_name,
7144                                 smb_fname_dst->base_name));
7145
7146                         status = copy_file(ctx, conn, smb_fname_src,
7147                                            smb_fname_dst, ofun, count,
7148                                            target_is_directory);
7149                         if (NT_STATUS_IS_OK(status)) {
7150                                 count++;
7151                         }
7152
7153                         TALLOC_FREE(talloced);
7154                 }
7155                 TALLOC_FREE(dir_hnd);
7156         }
7157
7158         if (count == 0) {
7159                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7160                 goto out;
7161         }
7162
7163         reply_outbuf(req, 1, 0);
7164         SSVAL(req->outbuf,smb_vwv0,count);
7165  out:
7166         TALLOC_FREE(smb_fname_src);
7167         TALLOC_FREE(smb_fname_dst);
7168         TALLOC_FREE(fname_src);
7169         TALLOC_FREE(fname_dst);
7170         TALLOC_FREE(fname_src_mask);
7171         TALLOC_FREE(fname_src_dir);
7172
7173         END_PROFILE(SMBcopy);
7174         return;
7175 }
7176
7177 #undef DBGC_CLASS
7178 #define DBGC_CLASS DBGC_LOCKING
7179
7180 /****************************************************************************
7181  Get a lock pid, dealing with large count requests.
7182 ****************************************************************************/
7183
7184 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7185                     bool large_file_format)
7186 {
7187         if(!large_file_format)
7188                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7189         else
7190                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7191 }
7192
7193 /****************************************************************************
7194  Get a lock count, dealing with large count requests.
7195 ****************************************************************************/
7196
7197 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7198                         bool large_file_format)
7199 {
7200         uint64_t count = 0;
7201
7202         if(!large_file_format) {
7203                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7204         } else {
7205
7206 #if defined(HAVE_LONGLONG)
7207                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7208                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7209 #else /* HAVE_LONGLONG */
7210
7211                 /*
7212                  * NT4.x seems to be broken in that it sends large file (64 bit)
7213                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7214                  * negotiated. For boxes without large unsigned ints truncate the
7215                  * lock count by dropping the top 32 bits.
7216                  */
7217
7218                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7219                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7220                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7221                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7222                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7223                 }
7224
7225                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7226 #endif /* HAVE_LONGLONG */
7227         }
7228
7229         return count;
7230 }
7231
7232 #if !defined(HAVE_LONGLONG)
7233 /****************************************************************************
7234  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7235 ****************************************************************************/
7236
7237 static uint32 map_lock_offset(uint32 high, uint32 low)
7238 {
7239         unsigned int i;
7240         uint32 mask = 0;
7241         uint32 highcopy = high;
7242
7243         /*
7244          * Try and find out how many significant bits there are in high.
7245          */
7246
7247         for(i = 0; highcopy; i++)
7248                 highcopy >>= 1;
7249
7250         /*
7251          * We use 31 bits not 32 here as POSIX
7252          * lock offsets may not be negative.
7253          */
7254
7255         mask = (~0) << (31 - i);
7256
7257         if(low & mask)
7258                 return 0; /* Fail. */
7259
7260         high <<= (31 - i);
7261
7262         return (high|low);
7263 }
7264 #endif /* !defined(HAVE_LONGLONG) */
7265
7266 /****************************************************************************
7267  Get a lock offset, dealing with large offset requests.
7268 ****************************************************************************/
7269
7270 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7271                          bool large_file_format, bool *err)
7272 {
7273         uint64_t offset = 0;
7274
7275         *err = False;
7276
7277         if(!large_file_format) {
7278                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7279         } else {
7280
7281 #if defined(HAVE_LONGLONG)
7282                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7283                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7284 #else /* HAVE_LONGLONG */
7285
7286                 /*
7287                  * NT4.x seems to be broken in that it sends large file (64 bit)
7288                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7289                  * negotiated. For boxes without large unsigned ints mangle the
7290                  * lock offset by mapping the top 32 bits onto the lower 32.
7291                  */
7292
7293                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7294                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7295                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7296                         uint32 new_low = 0;
7297
7298                         if((new_low = map_lock_offset(high, low)) == 0) {
7299                                 *err = True;
7300                                 return (uint64_t)-1;
7301                         }
7302
7303                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7304                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7305                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7306                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7307                 }
7308
7309                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7310 #endif /* HAVE_LONGLONG */
7311         }
7312
7313         return offset;
7314 }
7315
7316 NTSTATUS smbd_do_locking(struct smb_request *req,
7317                          files_struct *fsp,
7318                          uint8_t type,
7319                          int32_t timeout,
7320                          uint16_t num_ulocks,
7321                          struct smbd_lock_element *ulocks,
7322                          uint16_t num_locks,
7323                          struct smbd_lock_element *locks,
7324                          bool *async)
7325 {
7326         connection_struct *conn = req->conn;
7327         int i;
7328         NTSTATUS status = NT_STATUS_OK;
7329
7330         *async = false;
7331
7332         /* Data now points at the beginning of the list
7333            of smb_unlkrng structs */
7334         for(i = 0; i < (int)num_ulocks; i++) {
7335                 struct smbd_lock_element *e = &ulocks[i];
7336
7337                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7338                           "pid %u, file %s\n",
7339                           (double)e->offset,
7340                           (double)e->count,
7341                           (unsigned int)e->smblctx,
7342                           fsp_str_dbg(fsp)));
7343
7344                 if (e->brltype != UNLOCK_LOCK) {
7345                         /* this can only happen with SMB2 */
7346                         return NT_STATUS_INVALID_PARAMETER;
7347                 }
7348
7349                 status = do_unlock(req->sconn->msg_ctx,
7350                                 fsp,
7351                                 e->smblctx,
7352                                 e->count,
7353                                 e->offset,
7354                                 WINDOWS_LOCK);
7355
7356                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7357                     nt_errstr(status)));
7358
7359                 if (!NT_STATUS_IS_OK(status)) {
7360                         return status;
7361                 }
7362         }
7363
7364         /* Setup the timeout in seconds. */
7365
7366         if (!lp_blocking_locks(SNUM(conn))) {
7367                 timeout = 0;
7368         }
7369
7370         /* Data now points at the beginning of the list
7371            of smb_lkrng structs */
7372
7373         for(i = 0; i < (int)num_locks; i++) {
7374                 struct smbd_lock_element *e = &locks[i];
7375
7376                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7377                           "%llu, file %s timeout = %d\n",
7378                           (double)e->offset,
7379                           (double)e->count,
7380                           (unsigned long long)e->smblctx,
7381                           fsp_str_dbg(fsp),
7382                           (int)timeout));
7383
7384                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7385                         struct blocking_lock_record *blr = NULL;
7386
7387                         if (num_locks > 1) {
7388                                 /*
7389                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7390                                  * if the lock vector contains one entry. When given mutliple cancel
7391                                  * requests in a single PDU we expect the server to return an
7392                                  * error. Windows servers seem to accept the request but only
7393                                  * cancel the first lock.
7394                                  * JRA - Do what Windows does (tm) :-).
7395                                  */
7396
7397 #if 0
7398                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7399                                 return NT_STATUS_DOS(ERRDOS,
7400                                                 ERRcancelviolation);
7401 #else
7402                                 /* Windows behavior. */
7403                                 if (i != 0) {
7404                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7405                                                 "cancel request\n"));
7406                                         continue;
7407                                 }
7408 #endif
7409                         }
7410
7411                         if (lp_blocking_locks(SNUM(conn))) {
7412
7413                                 /* Schedule a message to ourselves to
7414                                    remove the blocking lock record and
7415                                    return the right error. */
7416
7417                                 blr = blocking_lock_cancel_smb1(fsp,
7418                                                 e->smblctx,
7419                                                 e->offset,
7420                                                 e->count,
7421                                                 WINDOWS_LOCK,
7422                                                 type,
7423                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7424                                 if (blr == NULL) {
7425                                         return NT_STATUS_DOS(
7426                                                         ERRDOS,
7427                                                         ERRcancelviolation);
7428                                 }
7429                         }
7430                         /* Remove a matching pending lock. */
7431                         status = do_lock_cancel(fsp,
7432                                                 e->smblctx,
7433                                                 e->count,
7434                                                 e->offset,
7435                                                 WINDOWS_LOCK,
7436                                                 blr);
7437                 } else {
7438                         bool blocking_lock = timeout ? true : false;
7439                         bool defer_lock = false;
7440                         struct byte_range_lock *br_lck;
7441                         uint64_t block_smblctx;
7442
7443                         br_lck = do_lock(req->sconn->msg_ctx,
7444                                         fsp,
7445                                         e->smblctx,
7446                                         e->count,
7447                                         e->offset, 
7448                                         e->brltype,
7449                                         WINDOWS_LOCK,
7450                                         blocking_lock,
7451                                         &status,
7452                                         &block_smblctx,
7453                                         NULL);
7454
7455                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7456                                 /* Windows internal resolution for blocking locks seems
7457                                    to be about 200ms... Don't wait for less than that. JRA. */
7458                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7459                                         timeout = lp_lock_spin_time();
7460                                 }
7461                                 defer_lock = true;
7462                         }
7463
7464                         /* If a lock sent with timeout of zero would fail, and
7465                          * this lock has been requested multiple times,
7466                          * according to brl_lock_failed() we convert this
7467                          * request to a blocking lock with a timeout of between
7468                          * 150 - 300 milliseconds.
7469                          *
7470                          * If lp_lock_spin_time() has been set to 0, we skip
7471                          * this blocking retry and fail immediately.
7472                          *
7473                          * Replacement for do_lock_spin(). JRA. */
7474
7475                         if (!req->sconn->using_smb2 &&
7476                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7477                             lp_lock_spin_time() && !blocking_lock &&
7478                             NT_STATUS_EQUAL((status),
7479                                 NT_STATUS_FILE_LOCK_CONFLICT))
7480                         {
7481                                 defer_lock = true;
7482                                 timeout = lp_lock_spin_time();
7483                         }
7484
7485                         if (br_lck && defer_lock) {
7486                                 /*
7487                                  * A blocking lock was requested. Package up
7488                                  * this smb into a queued request and push it
7489                                  * onto the blocking lock queue.
7490                                  */
7491                                 if(push_blocking_lock_request(br_lck,
7492                                                         req,
7493                                                         fsp,
7494                                                         timeout,
7495                                                         i,
7496                                                         e->smblctx,
7497                                                         e->brltype,
7498                                                         WINDOWS_LOCK,
7499                                                         e->offset,
7500                                                         e->count,
7501                                                         block_smblctx)) {
7502                                         TALLOC_FREE(br_lck);
7503                                         *async = true;
7504                                         return NT_STATUS_OK;
7505                                 }
7506                         }
7507
7508                         TALLOC_FREE(br_lck);
7509                 }
7510
7511                 if (!NT_STATUS_IS_OK(status)) {
7512                         break;
7513                 }
7514         }
7515
7516         /* If any of the above locks failed, then we must unlock
7517            all of the previous locks (X/Open spec). */
7518
7519         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7520
7521                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7522                         i = -1; /* we want to skip the for loop */
7523                 }
7524
7525                 /*
7526                  * Ensure we don't do a remove on the lock that just failed,
7527                  * as under POSIX rules, if we have a lock already there, we
7528                  * will delete it (and we shouldn't) .....
7529                  */
7530                 for(i--; i >= 0; i--) {
7531                         struct smbd_lock_element *e = &locks[i];
7532
7533                         do_unlock(req->sconn->msg_ctx,
7534                                 fsp,
7535                                 e->smblctx,
7536                                 e->count,
7537                                 e->offset,
7538                                 WINDOWS_LOCK);
7539                 }
7540                 return status;
7541         }
7542
7543         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7544                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7545
7546         return NT_STATUS_OK;
7547 }
7548
7549 /****************************************************************************
7550  Reply to a lockingX request.
7551 ****************************************************************************/
7552
7553 void reply_lockingX(struct smb_request *req)
7554 {
7555         connection_struct *conn = req->conn;
7556         files_struct *fsp;
7557         unsigned char locktype;
7558         unsigned char oplocklevel;
7559         uint16 num_ulocks;
7560         uint16 num_locks;
7561         int32 lock_timeout;
7562         int i;
7563         const uint8_t *data;
7564         bool large_file_format;
7565         bool err;
7566         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7567         struct smbd_lock_element *ulocks;
7568         struct smbd_lock_element *locks;
7569         bool async = false;
7570
7571         START_PROFILE(SMBlockingX);
7572
7573         if (req->wct < 8) {
7574                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7575                 END_PROFILE(SMBlockingX);
7576                 return;
7577         }
7578
7579         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7580         locktype = CVAL(req->vwv+3, 0);
7581         oplocklevel = CVAL(req->vwv+3, 1);
7582         num_ulocks = SVAL(req->vwv+6, 0);
7583         num_locks = SVAL(req->vwv+7, 0);
7584         lock_timeout = IVAL(req->vwv+4, 0);
7585         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7586
7587         if (!check_fsp(conn, req, fsp)) {
7588                 END_PROFILE(SMBlockingX);
7589                 return;
7590         }
7591
7592         data = req->buf;
7593
7594         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7595                 /* we don't support these - and CANCEL_LOCK makes w2k
7596                    and XP reboot so I don't really want to be
7597                    compatible! (tridge) */
7598                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7599                 END_PROFILE(SMBlockingX);
7600                 return;
7601         }
7602
7603         /* Check if this is an oplock break on a file
7604            we have granted an oplock on.
7605         */
7606         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7607                 /* Client can insist on breaking to none. */
7608                 bool break_to_none = (oplocklevel == 0);
7609                 bool result;
7610
7611                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7612                          "for fnum = %d\n", (unsigned int)oplocklevel,
7613                          fsp->fnum ));
7614
7615                 /*
7616                  * Make sure we have granted an exclusive or batch oplock on
7617                  * this file.
7618                  */
7619
7620                 if (fsp->oplock_type == 0) {
7621
7622                         /* The Samba4 nbench simulator doesn't understand
7623                            the difference between break to level2 and break
7624                            to none from level2 - it sends oplock break
7625                            replies in both cases. Don't keep logging an error
7626                            message here - just ignore it. JRA. */
7627
7628                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7629                                  "client for fnum = %d (oplock=%d) and no "
7630                                  "oplock granted on this file (%s).\n",
7631                                  fsp->fnum, fsp->oplock_type,
7632                                  fsp_str_dbg(fsp)));
7633
7634                         /* if this is a pure oplock break request then don't
7635                          * send a reply */
7636                         if (num_locks == 0 && num_ulocks == 0) {
7637                                 END_PROFILE(SMBlockingX);
7638                                 return;
7639                         } else {
7640                                 END_PROFILE(SMBlockingX);
7641                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7642                                 return;
7643                         }
7644                 }
7645
7646                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7647                     (break_to_none)) {
7648                         result = remove_oplock(fsp);
7649                 } else {
7650                         result = downgrade_oplock(fsp);
7651                 }
7652
7653                 if (!result) {
7654                         DEBUG(0, ("reply_lockingX: error in removing "
7655                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7656                         /* Hmmm. Is this panic justified? */
7657                         smb_panic("internal tdb error");
7658                 }
7659
7660                 reply_to_oplock_break_requests(fsp);
7661
7662                 /* if this is a pure oplock break request then don't send a
7663                  * reply */
7664                 if (num_locks == 0 && num_ulocks == 0) {
7665                         /* Sanity check - ensure a pure oplock break is not a
7666                            chained request. */
7667                         if(CVAL(req->vwv+0, 0) != 0xff)
7668                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7669                                          "break is a chained %d request !\n",
7670                                          (unsigned int)CVAL(req->vwv+0, 0)));
7671                         END_PROFILE(SMBlockingX);
7672                         return;
7673                 }
7674         }
7675
7676         if (req->buflen <
7677             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7678                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7679                 END_PROFILE(SMBlockingX);
7680                 return;
7681         }
7682
7683         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7684         if (ulocks == NULL) {
7685                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7686                 END_PROFILE(SMBlockingX);
7687                 return;
7688         }
7689
7690         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7691         if (locks == NULL) {
7692                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7693                 END_PROFILE(SMBlockingX);
7694                 return;
7695         }
7696
7697         /* Data now points at the beginning of the list
7698            of smb_unlkrng structs */
7699         for(i = 0; i < (int)num_ulocks; i++) {
7700                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7701                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7702                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7703                 ulocks[i].brltype = UNLOCK_LOCK;
7704
7705                 /*
7706                  * There is no error code marked "stupid client bug".... :-).
7707                  */
7708                 if(err) {
7709                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7710                         END_PROFILE(SMBlockingX);
7711                         return;
7712                 }
7713         }
7714
7715         /* Now do any requested locks */
7716         data += ((large_file_format ? 20 : 10)*num_ulocks);
7717
7718         /* Data now points at the beginning of the list
7719            of smb_lkrng structs */
7720
7721         for(i = 0; i < (int)num_locks; i++) {
7722                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7723                 locks[i].count = get_lock_count(data, i, large_file_format);
7724                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7725
7726                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7727                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7728                                 locks[i].brltype = PENDING_READ_LOCK;
7729                         } else {
7730                                 locks[i].brltype = READ_LOCK;
7731                         }
7732                 } else {
7733                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7734                                 locks[i].brltype = PENDING_WRITE_LOCK;
7735                         } else {
7736                                 locks[i].brltype = WRITE_LOCK;
7737                         }
7738                 }
7739
7740                 /*
7741                  * There is no error code marked "stupid client bug".... :-).
7742                  */
7743                 if(err) {
7744                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7745                         END_PROFILE(SMBlockingX);
7746                         return;
7747                 }
7748         }
7749
7750         status = smbd_do_locking(req, fsp,
7751                                  locktype, lock_timeout,
7752                                  num_ulocks, ulocks,
7753                                  num_locks, locks,
7754                                  &async);
7755         if (!NT_STATUS_IS_OK(status)) {
7756                 END_PROFILE(SMBlockingX);
7757                 reply_nterror(req, status);
7758                 return;
7759         }
7760         if (async) {
7761                 END_PROFILE(SMBlockingX);
7762                 return;
7763         }
7764
7765         reply_outbuf(req, 2, 0);
7766
7767         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7768                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7769
7770         END_PROFILE(SMBlockingX);
7771         chain_reply(req);
7772 }
7773
7774 #undef DBGC_CLASS
7775 #define DBGC_CLASS DBGC_ALL
7776
7777 /****************************************************************************
7778  Reply to a SMBreadbmpx (read block multiplex) request.
7779  Always reply with an error, if someone has a platform really needs this,
7780  please contact vl@samba.org
7781 ****************************************************************************/
7782
7783 void reply_readbmpx(struct smb_request *req)
7784 {
7785         START_PROFILE(SMBreadBmpx);
7786         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7787         END_PROFILE(SMBreadBmpx);
7788         return;
7789 }
7790
7791 /****************************************************************************
7792  Reply to a SMBreadbs (read block multiplex secondary) request.
7793  Always reply with an error, if someone has a platform really needs this,
7794  please contact vl@samba.org
7795 ****************************************************************************/
7796
7797 void reply_readbs(struct smb_request *req)
7798 {
7799         START_PROFILE(SMBreadBs);
7800         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7801         END_PROFILE(SMBreadBs);
7802         return;
7803 }
7804
7805 /****************************************************************************
7806  Reply to a SMBsetattrE.
7807 ****************************************************************************/
7808
7809 void reply_setattrE(struct smb_request *req)
7810 {
7811         connection_struct *conn = req->conn;
7812         struct smb_file_time ft;
7813         files_struct *fsp;
7814         NTSTATUS status;
7815
7816         START_PROFILE(SMBsetattrE);
7817         ZERO_STRUCT(ft);
7818
7819         if (req->wct < 7) {
7820                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7821                 goto out;
7822         }
7823
7824         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7825
7826         if(!fsp || (fsp->conn != conn)) {
7827                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7828                 goto out;
7829         }
7830
7831         /*
7832          * Convert the DOS times into unix times.
7833          */
7834
7835         ft.atime = convert_time_t_to_timespec(
7836             srv_make_unix_date2(req->vwv+3));
7837         ft.mtime = convert_time_t_to_timespec(
7838             srv_make_unix_date2(req->vwv+5));
7839         ft.create_time = convert_time_t_to_timespec(
7840             srv_make_unix_date2(req->vwv+1));
7841
7842         reply_outbuf(req, 0, 0);
7843
7844         /* 
7845          * Patch from Ray Frush <frush@engr.colostate.edu>
7846          * Sometimes times are sent as zero - ignore them.
7847          */
7848
7849         /* Ensure we have a valid stat struct for the source. */
7850         status = vfs_stat_fsp(fsp);
7851         if (!NT_STATUS_IS_OK(status)) {
7852                 reply_nterror(req, status);
7853                 goto out;
7854         }
7855
7856         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7857         if (!NT_STATUS_IS_OK(status)) {
7858                 reply_nterror(req, status);
7859                 goto out;
7860         }
7861
7862         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7863                " createtime=%u\n",
7864                 fsp->fnum,
7865                 (unsigned int)ft.atime.tv_sec,
7866                 (unsigned int)ft.mtime.tv_sec,
7867                 (unsigned int)ft.create_time.tv_sec
7868                 ));
7869  out:
7870         END_PROFILE(SMBsetattrE);
7871         return;
7872 }
7873
7874
7875 /* Back from the dead for OS/2..... JRA. */
7876
7877 /****************************************************************************
7878  Reply to a SMBwritebmpx (write block multiplex primary) request.
7879  Always reply with an error, if someone has a platform really needs this,
7880  please contact vl@samba.org
7881 ****************************************************************************/
7882
7883 void reply_writebmpx(struct smb_request *req)
7884 {
7885         START_PROFILE(SMBwriteBmpx);
7886         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7887         END_PROFILE(SMBwriteBmpx);
7888         return;
7889 }
7890
7891 /****************************************************************************
7892  Reply to a SMBwritebs (write block multiplex secondary) request.
7893  Always reply with an error, if someone has a platform really needs this,
7894  please contact vl@samba.org
7895 ****************************************************************************/
7896
7897 void reply_writebs(struct smb_request *req)
7898 {
7899         START_PROFILE(SMBwriteBs);
7900         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7901         END_PROFILE(SMBwriteBs);
7902         return;
7903 }
7904
7905 /****************************************************************************
7906  Reply to a SMBgetattrE.
7907 ****************************************************************************/
7908
7909 void reply_getattrE(struct smb_request *req)
7910 {
7911         connection_struct *conn = req->conn;
7912         int mode;
7913         files_struct *fsp;
7914         struct timespec create_ts;
7915
7916         START_PROFILE(SMBgetattrE);
7917
7918         if (req->wct < 1) {
7919                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7920                 END_PROFILE(SMBgetattrE);
7921                 return;
7922         }
7923
7924         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7925
7926         if(!fsp || (fsp->conn != conn)) {
7927                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7928                 END_PROFILE(SMBgetattrE);
7929                 return;
7930         }
7931
7932         /* Do an fstat on this file */
7933         if(fsp_stat(fsp)) {
7934                 reply_nterror(req, map_nt_error_from_unix(errno));
7935                 END_PROFILE(SMBgetattrE);
7936                 return;
7937         }
7938
7939         mode = dos_mode(conn, fsp->fsp_name);
7940
7941         /*
7942          * Convert the times into dos times. Set create
7943          * date to be last modify date as UNIX doesn't save
7944          * this.
7945          */
7946
7947         reply_outbuf(req, 11, 0);
7948
7949         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7950         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7951         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7952                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7953         /* Should we check pending modtime here ? JRA */
7954         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7955                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7956
7957         if (mode & aDIR) {
7958                 SIVAL(req->outbuf, smb_vwv6, 0);
7959                 SIVAL(req->outbuf, smb_vwv8, 0);
7960         } else {
7961                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7962                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7963                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7964         }
7965         SSVAL(req->outbuf,smb_vwv10, mode);
7966
7967         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7968
7969         END_PROFILE(SMBgetattrE);
7970         return;
7971 }