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