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