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