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