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