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