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