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