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