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