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