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