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