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