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