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