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