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