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