Start removing SMB_STRUCT_STAT variables except for
[samba.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "smbd/globals.h"
29
30 /****************************************************************************
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)
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(fsp->fsp_name->st.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_OFF_T size = 0;
3031
3032         START_PROFILE(SMBreadbraw);
3033
3034         if (srv_is_signing_active(smbd_server_conn) ||
3035             is_encrypted_packet(req->inbuf)) {
3036                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3037                         "raw reads/writes are disallowed.");
3038         }
3039
3040         if (req->wct < 8) {
3041                 reply_readbraw_error();
3042                 END_PROFILE(SMBreadbraw);
3043                 return;
3044         }
3045
3046         /*
3047          * Special check if an oplock break has been issued
3048          * and the readraw request croses on the wire, we must
3049          * return a zero length response here.
3050          */
3051
3052         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3053
3054         /*
3055          * We have to do a check_fsp by hand here, as
3056          * we must always return 4 zero bytes on error,
3057          * not a NTSTATUS.
3058          */
3059
3060         if (!fsp || !conn || conn != fsp->conn ||
3061                         req->vuid != fsp->vuid ||
3062                         fsp->is_directory || fsp->fh->fd == -1) {
3063                 /*
3064                  * fsp could be NULL here so use the value from the packet. JRA.
3065                  */
3066                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3067                         "- cache prime?\n",
3068                         (int)SVAL(req->vwv+0, 0)));
3069                 reply_readbraw_error();
3070                 END_PROFILE(SMBreadbraw);
3071                 return;
3072         }
3073
3074         /* Do a "by hand" version of CHECK_READ. */
3075         if (!(fsp->can_read ||
3076                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3077                                 (fsp->access_mask & FILE_EXECUTE)))) {
3078                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3079                                 (int)SVAL(req->vwv+0, 0)));
3080                 reply_readbraw_error();
3081                 END_PROFILE(SMBreadbraw);
3082                 return;
3083         }
3084
3085         flush_write_cache(fsp, READRAW_FLUSH);
3086
3087         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3088         if(req->wct == 10) {
3089                 /*
3090                  * This is a large offset (64 bit) read.
3091                  */
3092 #ifdef LARGE_SMB_OFF_T
3093
3094                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3095
3096 #else /* !LARGE_SMB_OFF_T */
3097
3098                 /*
3099                  * Ensure we haven't been sent a >32 bit offset.
3100                  */
3101
3102                 if(IVAL(req->vwv+8, 0) != 0) {
3103                         DEBUG(0,("reply_readbraw: large offset "
3104                                 "(%x << 32) used and we don't support "
3105                                 "64 bit offsets.\n",
3106                         (unsigned int)IVAL(req->vwv+8, 0) ));
3107                         reply_readbraw_error();
3108                         END_PROFILE(SMBreadbraw);
3109                         return;
3110                 }
3111
3112 #endif /* LARGE_SMB_OFF_T */
3113
3114                 if(startpos < 0) {
3115                         DEBUG(0,("reply_readbraw: negative 64 bit "
3116                                 "readraw offset (%.0f) !\n",
3117                                 (double)startpos ));
3118                         reply_readbraw_error();
3119                         END_PROFILE(SMBreadbraw);
3120                         return;
3121                 }
3122         }
3123
3124         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3125         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3126
3127         /* ensure we don't overrun the packet size */
3128         maxcount = MIN(65535,maxcount);
3129
3130         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3131             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3132             &lock);
3133
3134         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3135                 reply_readbraw_error();
3136                 END_PROFILE(SMBreadbraw);
3137                 return;
3138         }
3139
3140         if (fsp_stat(fsp) == 0) {
3141                 size = fsp->fsp_name->st.st_ex_size;
3142         }
3143
3144         if (startpos >= size) {
3145                 nread = 0;
3146         } else {
3147                 nread = MIN(maxcount,(size - startpos));
3148         }
3149
3150 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3151         if (nread < mincount)
3152                 nread = 0;
3153 #endif
3154
3155         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3156                 "min=%lu nread=%lu\n",
3157                 fsp->fnum, (double)startpos,
3158                 (unsigned long)maxcount,
3159                 (unsigned long)mincount,
3160                 (unsigned long)nread ) );
3161
3162         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3163
3164         DEBUG(5,("reply_readbraw finished\n"));
3165
3166         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3167
3168         END_PROFILE(SMBreadbraw);
3169         return;
3170 }
3171
3172 #undef DBGC_CLASS
3173 #define DBGC_CLASS DBGC_LOCKING
3174
3175 /****************************************************************************
3176  Reply to a lockread (core+ protocol).
3177 ****************************************************************************/
3178
3179 void reply_lockread(struct smb_request *req)
3180 {
3181         connection_struct *conn = req->conn;
3182         ssize_t nread = -1;
3183         char *data;
3184         SMB_OFF_T startpos;
3185         size_t numtoread;
3186         NTSTATUS status;
3187         files_struct *fsp;
3188         struct byte_range_lock *br_lck = NULL;
3189         char *p = NULL;
3190         struct smbd_server_connection *sconn = smbd_server_conn;
3191
3192         START_PROFILE(SMBlockread);
3193
3194         if (req->wct < 5) {
3195                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3196                 END_PROFILE(SMBlockread);
3197                 return;
3198         }
3199
3200         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3201
3202         if (!check_fsp(conn, req, fsp)) {
3203                 END_PROFILE(SMBlockread);
3204                 return;
3205         }
3206
3207         if (!CHECK_READ(fsp,req)) {
3208                 reply_doserror(req, ERRDOS, ERRbadaccess);
3209                 END_PROFILE(SMBlockread);
3210                 return;
3211         }
3212
3213         numtoread = SVAL(req->vwv+1, 0);
3214         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3215
3216         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3217
3218         reply_outbuf(req, 5, numtoread + 3);
3219
3220         data = smb_buf(req->outbuf) + 3;
3221
3222         /*
3223          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3224          * protocol request that predates the read/write lock concept. 
3225          * Thus instead of asking for a read lock here we need to ask
3226          * for a write lock. JRA.
3227          * Note that the requested lock size is unaffected by max_recv.
3228          */
3229
3230         br_lck = do_lock(smbd_messaging_context(),
3231                         fsp,
3232                         req->smbpid,
3233                         (uint64_t)numtoread,
3234                         (uint64_t)startpos,
3235                         WRITE_LOCK,
3236                         WINDOWS_LOCK,
3237                         False, /* Non-blocking lock. */
3238                         &status,
3239                         NULL,
3240                         NULL);
3241         TALLOC_FREE(br_lck);
3242
3243         if (NT_STATUS_V(status)) {
3244                 reply_nterror(req, status);
3245                 END_PROFILE(SMBlockread);
3246                 return;
3247         }
3248
3249         /*
3250          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3251          */
3252
3253         if (numtoread > sconn->smb1.negprot.max_recv) {
3254                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3255 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3256                         (unsigned int)numtoread,
3257                         (unsigned int)sconn->smb1.negprot.max_recv));
3258                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3259         }
3260         nread = read_file(fsp,data,startpos,numtoread);
3261
3262         if (nread < 0) {
3263                 reply_nterror(req, map_nt_error_from_unix(errno));
3264                 END_PROFILE(SMBlockread);
3265                 return;
3266         }
3267
3268         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3269
3270         SSVAL(req->outbuf,smb_vwv0,nread);
3271         SSVAL(req->outbuf,smb_vwv5,nread+3);
3272         p = smb_buf(req->outbuf);
3273         SCVAL(p,0,0); /* pad byte. */
3274         SSVAL(p,1,nread);
3275
3276         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3277                  fsp->fnum, (int)numtoread, (int)nread));
3278
3279         END_PROFILE(SMBlockread);
3280         return;
3281 }
3282
3283 #undef DBGC_CLASS
3284 #define DBGC_CLASS DBGC_ALL
3285
3286 /****************************************************************************
3287  Reply to a read.
3288 ****************************************************************************/
3289
3290 void reply_read(struct smb_request *req)
3291 {
3292         connection_struct *conn = req->conn;
3293         size_t numtoread;
3294         ssize_t nread = 0;
3295         char *data;
3296         SMB_OFF_T startpos;
3297         int outsize = 0;
3298         files_struct *fsp;
3299         struct lock_struct lock;
3300         struct smbd_server_connection *sconn = smbd_server_conn;
3301
3302         START_PROFILE(SMBread);
3303
3304         if (req->wct < 3) {
3305                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3306                 END_PROFILE(SMBread);
3307                 return;
3308         }
3309
3310         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3311
3312         if (!check_fsp(conn, req, fsp)) {
3313                 END_PROFILE(SMBread);
3314                 return;
3315         }
3316
3317         if (!CHECK_READ(fsp,req)) {
3318                 reply_doserror(req, ERRDOS, ERRbadaccess);
3319                 END_PROFILE(SMBread);
3320                 return;
3321         }
3322
3323         numtoread = SVAL(req->vwv+1, 0);
3324         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3325
3326         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3327
3328         /*
3329          * The requested read size cannot be greater than max_recv. JRA.
3330          */
3331         if (numtoread > sconn->smb1.negprot.max_recv) {
3332                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3333 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3334                         (unsigned int)numtoread,
3335                         (unsigned int)sconn->smb1.negprot.max_recv));
3336                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3337         }
3338
3339         reply_outbuf(req, 5, numtoread+3);
3340
3341         data = smb_buf(req->outbuf) + 3;
3342
3343         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3344             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3345             &lock);
3346
3347         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3348                 reply_doserror(req, ERRDOS,ERRlock);
3349                 END_PROFILE(SMBread);
3350                 return;
3351         }
3352
3353         if (numtoread > 0)
3354                 nread = read_file(fsp,data,startpos,numtoread);
3355
3356         if (nread < 0) {
3357                 reply_nterror(req, map_nt_error_from_unix(errno));
3358                 goto strict_unlock;
3359         }
3360
3361         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3362
3363         SSVAL(req->outbuf,smb_vwv0,nread);
3364         SSVAL(req->outbuf,smb_vwv5,nread+3);
3365         SCVAL(smb_buf(req->outbuf),0,1);
3366         SSVAL(smb_buf(req->outbuf),1,nread);
3367
3368         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3369                 fsp->fnum, (int)numtoread, (int)nread ) );
3370
3371 strict_unlock:
3372         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3373
3374         END_PROFILE(SMBread);
3375         return;
3376 }
3377
3378 /****************************************************************************
3379  Setup readX header.
3380 ****************************************************************************/
3381
3382 static int setup_readX_header(struct smb_request *req, char *outbuf,
3383                               size_t smb_maxcnt)
3384 {
3385         int outsize;
3386         char *data;
3387
3388         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3389         data = smb_buf(outbuf);
3390
3391         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3392
3393         SCVAL(outbuf,smb_vwv0,0xFF);
3394         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3395         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3396         SSVAL(outbuf,smb_vwv6,
3397               req_wct_ofs(req)
3398               + 1               /* the wct field */
3399               + 12 * sizeof(uint16_t) /* vwv */
3400               + 2);             /* the buflen field */
3401         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3402         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3403         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3404         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3405         return outsize;
3406 }
3407
3408 /****************************************************************************
3409  Reply to a read and X - possibly using sendfile.
3410 ****************************************************************************/
3411
3412 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3413                             files_struct *fsp, SMB_OFF_T startpos,
3414                             size_t smb_maxcnt)
3415 {
3416         ssize_t nread = -1;
3417         struct lock_struct lock;
3418         int saved_errno = 0;
3419
3420         if(fsp_stat(fsp) == -1) {
3421                 reply_nterror(req, map_nt_error_from_unix(errno));
3422                 return;
3423         }
3424
3425         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3426             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3427             &lock);
3428
3429         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3430                 reply_doserror(req, ERRDOS, ERRlock);
3431                 return;
3432         }
3433
3434         if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3435                         (startpos > fsp->fsp_name->st.st_ex_size)
3436                         || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3437                 /*
3438                  * We already know that we would do a short read, so don't
3439                  * try the sendfile() path.
3440                  */
3441                 goto nosendfile_read;
3442         }
3443
3444 #if defined(WITH_SENDFILE)
3445         /*
3446          * We can only use sendfile on a non-chained packet
3447          * but we can use on a non-oplocked file. tridge proved this
3448          * on a train in Germany :-). JRA.
3449          */
3450
3451         if (!req_is_in_chain(req) &&
3452             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3453             (fsp->wcp == NULL) &&
3454             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3455                 uint8 headerbuf[smb_size + 12 * 2];
3456                 DATA_BLOB header;
3457
3458                 /*
3459                  * Set up the packet header before send. We
3460                  * assume here the sendfile will work (get the
3461                  * correct amount of data).
3462                  */
3463
3464                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3465
3466                 construct_reply_common_req(req, (char *)headerbuf);
3467                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3468
3469                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3470                         /* Returning ENOSYS means no data at all was sent.
3471                            Do this as a normal read. */
3472                         if (errno == ENOSYS) {
3473                                 goto normal_read;
3474                         }
3475
3476                         /*
3477                          * Special hack for broken Linux with no working sendfile. If we
3478                          * return EINTR we sent the header but not the rest of the data.
3479                          * Fake this up by doing read/write calls.
3480                          */
3481
3482                         if (errno == EINTR) {
3483                                 /* Ensure we don't do this again. */
3484                                 set_use_sendfile(SNUM(conn), False);
3485                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3486                                 nread = fake_sendfile(fsp, startpos,
3487                                                       smb_maxcnt);
3488                                 if (nread == -1) {
3489                                         DEBUG(0,("send_file_readX: "
3490                                                  "fake_sendfile failed for "
3491                                                  "file %s (%s).\n",
3492                                                  fsp_str_dbg(fsp),
3493                                                  strerror(errno)));
3494                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3495                                 }
3496                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3497                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3498                                 /* No outbuf here means successful sendfile. */
3499                                 goto strict_unlock;
3500                         }
3501
3502                         DEBUG(0,("send_file_readX: sendfile failed for file "
3503                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3504                                  strerror(errno)));
3505                         exit_server_cleanly("send_file_readX sendfile failed");
3506                 } else if (nread == 0) {
3507                         /*
3508                          * Some sendfile implementations return 0 to indicate
3509                          * that there was a short read, but nothing was
3510                          * actually written to the socket.  In this case,
3511                          * fallback to the normal read path so the header gets
3512                          * the correct byte count.
3513                          */
3514                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3515                                   "falling back to the normal read: %s\n",
3516                                   fsp_str_dbg(fsp)));
3517                         goto normal_read;
3518                 }
3519
3520                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3521                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3522
3523                 /* Deal with possible short send. */
3524                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3525                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3526                 }
3527                 /* No outbuf here means successful sendfile. */
3528                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3529                 SMB_PERFCOUNT_END(&req->pcd);
3530                 goto strict_unlock;
3531         }
3532
3533 normal_read:
3534
3535 #endif
3536
3537         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3538                 uint8 headerbuf[smb_size + 2*12];
3539
3540                 construct_reply_common_req(req, (char *)headerbuf);
3541                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3542
3543                 /* Send out the header. */
3544                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3545                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3546                         DEBUG(0,("send_file_readX: write_data failed for file "
3547                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3548                                  strerror(errno)));
3549                         exit_server_cleanly("send_file_readX sendfile failed");
3550                 }
3551                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3552                 if (nread == -1) {
3553                         DEBUG(0,("send_file_readX: fake_sendfile failed for "
3554                                  "file %s (%s).\n", fsp_str_dbg(fsp),
3555                                  strerror(errno)));
3556                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3557                 }
3558                 goto strict_unlock;
3559         }
3560
3561 nosendfile_read:
3562
3563         reply_outbuf(req, 12, smb_maxcnt);
3564
3565         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3566         saved_errno = errno;
3567
3568         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3569
3570         if (nread < 0) {
3571                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3572                 return;
3573         }
3574
3575         setup_readX_header(req, (char *)req->outbuf, nread);
3576
3577         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3578                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3579
3580         chain_reply(req);
3581         return;
3582
3583  strict_unlock:
3584         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3585         TALLOC_FREE(req->outbuf);
3586         return;
3587 }
3588
3589 /****************************************************************************
3590  Reply to a read and X.
3591 ****************************************************************************/
3592
3593 void reply_read_and_X(struct smb_request *req)
3594 {
3595         connection_struct *conn = req->conn;
3596         files_struct *fsp;
3597         SMB_OFF_T startpos;
3598         size_t smb_maxcnt;
3599         bool big_readX = False;
3600 #if 0
3601         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3602 #endif
3603
3604         START_PROFILE(SMBreadX);
3605
3606         if ((req->wct != 10) && (req->wct != 12)) {
3607                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3608                 return;
3609         }
3610
3611         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3612         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3613         smb_maxcnt = SVAL(req->vwv+5, 0);
3614
3615         /* If it's an IPC, pass off the pipe handler. */
3616         if (IS_IPC(conn)) {
3617                 reply_pipe_read_and_X(req);
3618                 END_PROFILE(SMBreadX);
3619                 return;
3620         }
3621
3622         if (!check_fsp(conn, req, fsp)) {
3623                 END_PROFILE(SMBreadX);
3624                 return;
3625         }
3626
3627         if (!CHECK_READ(fsp,req)) {
3628                 reply_doserror(req, ERRDOS,ERRbadaccess);
3629                 END_PROFILE(SMBreadX);
3630                 return;
3631         }
3632
3633         if (global_client_caps & CAP_LARGE_READX) {
3634                 size_t upper_size = SVAL(req->vwv+7, 0);
3635                 smb_maxcnt |= (upper_size<<16);
3636                 if (upper_size > 1) {
3637                         /* Can't do this on a chained packet. */
3638                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3639                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3640                                 END_PROFILE(SMBreadX);
3641                                 return;
3642                         }
3643                         /* We currently don't do this on signed or sealed data. */
3644                         if (srv_is_signing_active(smbd_server_conn) ||
3645                             is_encrypted_packet(req->inbuf)) {
3646                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3647                                 END_PROFILE(SMBreadX);
3648                                 return;
3649                         }
3650                         /* Is there room in the reply for this data ? */
3651                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3652                                 reply_nterror(req,
3653                                               NT_STATUS_INVALID_PARAMETER);
3654                                 END_PROFILE(SMBreadX);
3655                                 return;
3656                         }
3657                         big_readX = True;
3658                 }
3659         }
3660
3661         if (req->wct == 12) {
3662 #ifdef LARGE_SMB_OFF_T
3663                 /*
3664                  * This is a large offset (64 bit) read.
3665                  */
3666                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3667
3668 #else /* !LARGE_SMB_OFF_T */
3669
3670                 /*
3671                  * Ensure we haven't been sent a >32 bit offset.
3672                  */
3673
3674                 if(IVAL(req->vwv+10, 0) != 0) {
3675                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3676                                  "used and we don't support 64 bit offsets.\n",
3677                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3678                         END_PROFILE(SMBreadX);
3679                         reply_doserror(req, ERRDOS, ERRbadaccess);
3680                         return;
3681                 }
3682
3683 #endif /* LARGE_SMB_OFF_T */
3684
3685         }
3686
3687         if (!big_readX &&
3688             schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3689                 goto out;
3690         }
3691
3692         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3693
3694  out:
3695         END_PROFILE(SMBreadX);
3696         return;
3697 }
3698
3699 /****************************************************************************
3700  Error replies to writebraw must have smb_wct == 1. Fix this up.
3701 ****************************************************************************/
3702
3703 void error_to_writebrawerr(struct smb_request *req)
3704 {
3705         uint8 *old_outbuf = req->outbuf;
3706
3707         reply_outbuf(req, 1, 0);
3708
3709         memcpy(req->outbuf, old_outbuf, smb_size);
3710         TALLOC_FREE(old_outbuf);
3711 }
3712
3713 /****************************************************************************
3714  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3715 ****************************************************************************/
3716
3717 void reply_writebraw(struct smb_request *req)
3718 {
3719         connection_struct *conn = req->conn;
3720         char *buf = NULL;
3721         ssize_t nwritten=0;
3722         ssize_t total_written=0;
3723         size_t numtowrite=0;
3724         size_t tcount;
3725         SMB_OFF_T startpos;
3726         char *data=NULL;
3727         bool write_through;
3728         files_struct *fsp;
3729         struct lock_struct lock;
3730         NTSTATUS status;
3731
3732         START_PROFILE(SMBwritebraw);
3733
3734         /*
3735          * If we ever reply with an error, it must have the SMB command
3736          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3737          * we're finished.
3738          */
3739         SCVAL(req->inbuf,smb_com,SMBwritec);
3740
3741         if (srv_is_signing_active(smbd_server_conn)) {
3742                 END_PROFILE(SMBwritebraw);
3743                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3744                                 "raw reads/writes are disallowed.");
3745         }
3746
3747         if (req->wct < 12) {
3748                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3749                 error_to_writebrawerr(req);
3750                 END_PROFILE(SMBwritebraw);
3751                 return;
3752         }
3753
3754         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3755         if (!check_fsp(conn, req, fsp)) {
3756                 error_to_writebrawerr(req);
3757                 END_PROFILE(SMBwritebraw);
3758                 return;
3759         }
3760
3761         if (!CHECK_WRITE(fsp)) {
3762                 reply_doserror(req, ERRDOS, ERRbadaccess);
3763                 error_to_writebrawerr(req);
3764                 END_PROFILE(SMBwritebraw);
3765                 return;
3766         }
3767
3768         tcount = IVAL(req->vwv+1, 0);
3769         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3770         write_through = BITSETW(req->vwv+7,0);
3771
3772         /* We have to deal with slightly different formats depending
3773                 on whether we are using the core+ or lanman1.0 protocol */
3774
3775         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3776                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3777                 data = smb_buf(req->inbuf);
3778         } else {
3779                 numtowrite = SVAL(req->vwv+10, 0);
3780                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3781         }
3782
3783         /* Ensure we don't write bytes past the end of this packet. */
3784         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3785                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3786                 error_to_writebrawerr(req);
3787                 END_PROFILE(SMBwritebraw);
3788                 return;
3789         }
3790
3791         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3792             (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3793             &lock);
3794
3795         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3796                 reply_doserror(req, ERRDOS, ERRlock);
3797                 error_to_writebrawerr(req);
3798                 END_PROFILE(SMBwritebraw);
3799                 return;
3800         }
3801
3802         if (numtowrite>0) {
3803                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3804         }
3805
3806         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3807                         "wrote=%d sync=%d\n",
3808                 fsp->fnum, (double)startpos, (int)numtowrite,
3809                 (int)nwritten, (int)write_through));
3810
3811         if (nwritten < (ssize_t)numtowrite)  {
3812                 reply_doserror(req, ERRHRD, ERRdiskfull);
3813                 error_to_writebrawerr(req);
3814                 goto strict_unlock;
3815         }
3816
3817         total_written = nwritten;
3818
3819         /* Allocate a buffer of 64k + length. */
3820         buf = TALLOC_ARRAY(NULL, char, 65540);
3821         if (!buf) {
3822                 reply_doserror(req, ERRDOS, ERRnomem);
3823                 error_to_writebrawerr(req);
3824                 goto strict_unlock;
3825         }
3826
3827         /* Return a SMBwritebraw message to the redirector to tell
3828          * it to send more bytes */
3829
3830         memcpy(buf, req->inbuf, smb_size);
3831         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3832         SCVAL(buf,smb_com,SMBwritebraw);
3833         SSVALS(buf,smb_vwv0,0xFFFF);
3834         show_msg(buf);
3835         if (!srv_send_smb(smbd_server_fd(),
3836                           buf,
3837                           false, 0, /* no signing */
3838                           IS_CONN_ENCRYPTED(conn),
3839                           &req->pcd)) {
3840                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3841                         "failed.");
3842         }
3843
3844         /* Now read the raw data into the buffer and write it */
3845         status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3846                                  &numtowrite);
3847         if (!NT_STATUS_IS_OK(status)) {
3848                 exit_server_cleanly("secondary writebraw failed");
3849         }
3850
3851         /* Set up outbuf to return the correct size */
3852         reply_outbuf(req, 1, 0);
3853
3854         if (numtowrite != 0) {
3855
3856                 if (numtowrite > 0xFFFF) {
3857                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3858                                 "raw requested (%u). Terminating\n",
3859                                 (unsigned int)numtowrite ));
3860                         exit_server_cleanly("secondary writebraw failed");
3861                 }
3862
3863                 if (tcount > nwritten+numtowrite) {
3864                         DEBUG(3,("reply_writebraw: Client overestimated the "
3865                                 "write %d %d %d\n",
3866                                 (int)tcount,(int)nwritten,(int)numtowrite));
3867                 }
3868
3869                 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3870
3871                 if (!NT_STATUS_IS_OK(status)) {
3872                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3873                                  "raw read failed (%s). Terminating\n",
3874                                  nt_errstr(status)));
3875                         exit_server_cleanly("secondary writebraw failed");
3876                 }
3877
3878                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3879                 if (nwritten == -1) {
3880                         TALLOC_FREE(buf);
3881                         reply_nterror(req, map_nt_error_from_unix(errno));
3882                         error_to_writebrawerr(req);
3883                         goto strict_unlock;
3884                 }
3885
3886                 if (nwritten < (ssize_t)numtowrite) {
3887                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3888                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3889                 }
3890
3891                 if (nwritten > 0) {
3892                         total_written += nwritten;
3893                 }
3894         }
3895
3896         TALLOC_FREE(buf);
3897         SSVAL(req->outbuf,smb_vwv0,total_written);
3898
3899         status = sync_file(conn, fsp, write_through);
3900         if (!NT_STATUS_IS_OK(status)) {
3901                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3902                          fsp_str_dbg(fsp), nt_errstr(status)));
3903                 reply_nterror(req, status);
3904                 error_to_writebrawerr(req);
3905                 goto strict_unlock;
3906         }
3907
3908         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3909                 "wrote=%d\n",
3910                 fsp->fnum, (double)startpos, (int)numtowrite,
3911                 (int)total_written));
3912
3913         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3914
3915         /* We won't return a status if write through is not selected - this
3916          * follows what WfWg does */
3917         END_PROFILE(SMBwritebraw);
3918
3919         if (!write_through && total_written==tcount) {
3920
3921 #if RABBIT_PELLET_FIX
3922                 /*
3923                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3924                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3925                  * JRA.
3926                  */
3927                 if (!send_keepalive(smbd_server_fd())) {
3928                         exit_server_cleanly("reply_writebraw: send of "
3929                                 "keepalive failed");
3930                 }
3931 #endif
3932                 TALLOC_FREE(req->outbuf);
3933         }
3934         return;
3935
3936 strict_unlock:
3937         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3938
3939         END_PROFILE(SMBwritebraw);
3940         return;
3941 }
3942
3943 #undef DBGC_CLASS
3944 #define DBGC_CLASS DBGC_LOCKING
3945
3946 /****************************************************************************
3947  Reply to a writeunlock (core+).
3948 ****************************************************************************/
3949
3950 void reply_writeunlock(struct smb_request *req)
3951 {
3952         connection_struct *conn = req->conn;
3953         ssize_t nwritten = -1;
3954         size_t numtowrite;
3955         SMB_OFF_T startpos;
3956         const char *data;
3957         NTSTATUS status = NT_STATUS_OK;
3958         files_struct *fsp;
3959         struct lock_struct lock;
3960         int saved_errno = 0;
3961
3962         START_PROFILE(SMBwriteunlock);
3963
3964         if (req->wct < 5) {
3965                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3966                 END_PROFILE(SMBwriteunlock);
3967                 return;
3968         }
3969
3970         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3971
3972         if (!check_fsp(conn, req, fsp)) {
3973                 END_PROFILE(SMBwriteunlock);
3974                 return;
3975         }
3976
3977         if (!CHECK_WRITE(fsp)) {
3978                 reply_doserror(req, ERRDOS,ERRbadaccess);
3979                 END_PROFILE(SMBwriteunlock);
3980                 return;
3981         }
3982
3983         numtowrite = SVAL(req->vwv+1, 0);
3984         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3985         data = (const char *)req->buf + 3;
3986
3987         if (numtowrite) {
3988                 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3989                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3990                     &lock);
3991
3992                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3993                         reply_doserror(req, ERRDOS, ERRlock);
3994                         END_PROFILE(SMBwriteunlock);
3995                         return;
3996                 }
3997         }
3998
3999         /* The special X/Open SMB protocol handling of
4000            zero length writes is *NOT* done for
4001            this call */
4002         if(numtowrite == 0) {
4003                 nwritten = 0;
4004         } else {
4005                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4006                 saved_errno = errno;
4007         }
4008
4009         status = sync_file(conn, fsp, False /* write through */);
4010         if (!NT_STATUS_IS_OK(status)) {
4011                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4012                          fsp_str_dbg(fsp), nt_errstr(status)));
4013                 reply_nterror(req, status);
4014                 goto strict_unlock;
4015         }
4016
4017         if(nwritten < 0) {
4018                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4019                 goto strict_unlock;
4020         }
4021
4022         if((nwritten < numtowrite) && (numtowrite != 0)) {
4023                 reply_doserror(req, ERRHRD, ERRdiskfull);
4024                 goto strict_unlock;
4025         }
4026
4027         if (numtowrite) {
4028                 status = do_unlock(smbd_messaging_context(),
4029                                 fsp,
4030                                 req->smbpid,
4031                                 (uint64_t)numtowrite, 
4032                                 (uint64_t)startpos,
4033                                 WINDOWS_LOCK);
4034
4035                 if (NT_STATUS_V(status)) {
4036                         reply_nterror(req, status);
4037                         goto strict_unlock;
4038                 }
4039         }
4040
4041         reply_outbuf(req, 1, 0);
4042
4043         SSVAL(req->outbuf,smb_vwv0,nwritten);
4044
4045         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4046                  fsp->fnum, (int)numtowrite, (int)nwritten));
4047
4048 strict_unlock:
4049         if (numtowrite) {
4050                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4051         }
4052
4053         END_PROFILE(SMBwriteunlock);
4054         return;
4055 }
4056
4057 #undef DBGC_CLASS
4058 #define DBGC_CLASS DBGC_ALL
4059
4060 /****************************************************************************
4061  Reply to a write.
4062 ****************************************************************************/
4063
4064 void reply_write(struct smb_request *req)
4065 {
4066         connection_struct *conn = req->conn;
4067         size_t numtowrite;
4068         ssize_t nwritten = -1;
4069         SMB_OFF_T startpos;
4070         const char *data;
4071         files_struct *fsp;
4072         struct lock_struct lock;
4073         NTSTATUS status;
4074         int saved_errno = 0;
4075
4076         START_PROFILE(SMBwrite);
4077
4078         if (req->wct < 5) {
4079                 END_PROFILE(SMBwrite);
4080                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4081                 return;
4082         }
4083
4084         /* If it's an IPC, pass off the pipe handler. */
4085         if (IS_IPC(conn)) {
4086                 reply_pipe_write(req);
4087                 END_PROFILE(SMBwrite);
4088                 return;
4089         }
4090
4091         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4092
4093         if (!check_fsp(conn, req, fsp)) {
4094                 END_PROFILE(SMBwrite);
4095                 return;
4096         }
4097
4098         if (!CHECK_WRITE(fsp)) {
4099                 reply_doserror(req, ERRDOS, ERRbadaccess);
4100                 END_PROFILE(SMBwrite);
4101                 return;
4102         }
4103
4104         numtowrite = SVAL(req->vwv+1, 0);
4105         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4106         data = (const char *)req->buf + 3;
4107
4108         init_strict_lock_struct(fsp, (uint32)req->smbpid,
4109             (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4110             &lock);
4111
4112         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4113                 reply_doserror(req, ERRDOS, ERRlock);
4114                 END_PROFILE(SMBwrite);
4115                 return;
4116         }
4117
4118         /*
4119          * X/Open SMB protocol says that if smb_vwv1 is
4120          * zero then the file size should be extended or
4121          * truncated to the size given in smb_vwv[2-3].
4122          */
4123
4124         if(numtowrite == 0) {
4125                 /*
4126                  * This is actually an allocate call, and set EOF. JRA.
4127                  */
4128                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4129                 if (nwritten < 0) {
4130                         reply_nterror(req, NT_STATUS_DISK_FULL);
4131                         goto strict_unlock;
4132                 }
4133                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4134                 if (nwritten < 0) {
4135                         reply_nterror(req, NT_STATUS_DISK_FULL);
4136                         goto strict_unlock;
4137                 }
4138                 trigger_write_time_update_immediate(fsp);
4139         } else {
4140                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4141         }
4142
4143         status = sync_file(conn, fsp, False);
4144         if (!NT_STATUS_IS_OK(status)) {
4145                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4146                          fsp_str_dbg(fsp), nt_errstr(status)));
4147                 reply_nterror(req, status);
4148                 goto strict_unlock;
4149         }
4150
4151         if(nwritten < 0) {
4152                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4153                 goto strict_unlock;
4154         }
4155
4156         if((nwritten == 0) && (numtowrite != 0)) {
4157                 reply_doserror(req, ERRHRD, ERRdiskfull);
4158                 goto strict_unlock;
4159         }
4160
4161         reply_outbuf(req, 1, 0);
4162
4163         SSVAL(req->outbuf,smb_vwv0,nwritten);
4164
4165         if (nwritten < (ssize_t)numtowrite) {
4166                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4167                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4168         }
4169
4170         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4171
4172 strict_unlock:
4173         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4174
4175         END_PROFILE(SMBwrite);
4176         return;
4177 }
4178
4179 /****************************************************************************
4180  Ensure a buffer is a valid writeX for recvfile purposes.
4181 ****************************************************************************/
4182
4183 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4184                                                 (2*14) + /* word count (including bcc) */ \
4185                                                 1 /* pad byte */)
4186
4187 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4188 {
4189         size_t numtowrite;
4190         connection_struct *conn = NULL;
4191         unsigned int doff = 0;
4192         size_t len = smb_len_large(inbuf);
4193         struct smbd_server_connection *sconn = smbd_server_conn;
4194
4195         if (is_encrypted_packet(inbuf)) {
4196                 /* Can't do this on encrypted
4197                  * connections. */
4198                 return false;
4199         }
4200
4201         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4202                 return false;
4203         }
4204
4205         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4206                         CVAL(inbuf,smb_wct) != 14) {
4207                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4208                         "invalid word length.\n"));
4209                 return false;
4210         }
4211
4212         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4213         if (conn == NULL) {
4214                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4215                 return false;
4216         }
4217         if (IS_IPC(conn)) {
4218                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4219                 return false;
4220         }
4221         if (IS_PRINT(conn)) {
4222                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4223                 return false;
4224         }
4225         doff = SVAL(inbuf,smb_vwv11);
4226
4227         numtowrite = SVAL(inbuf,smb_vwv10);
4228
4229         if (len > doff && len - doff > 0xFFFF) {
4230                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4231         }
4232
4233         if (numtowrite == 0) {
4234                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4235                 return false;
4236         }
4237
4238         /* Ensure the sizes match up. */
4239         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4240                 /* no pad byte...old smbclient :-( */
4241                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4242                         (unsigned int)doff,
4243                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4244                 return false;
4245         }
4246
4247         if (len - doff != numtowrite) {
4248                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4249                         "len = %u, doff = %u, numtowrite = %u\n",
4250                         (unsigned int)len,
4251                         (unsigned int)doff,
4252                         (unsigned int)numtowrite ));
4253                 return false;
4254         }
4255
4256         DEBUG(10,("is_valid_writeX_buffer: true "
4257                 "len = %u, doff = %u, numtowrite = %u\n",
4258                 (unsigned int)len,
4259                 (unsigned int)doff,
4260                 (unsigned int)numtowrite ));
4261
4262         return true;
4263 }
4264
4265 /****************************************************************************
4266  Reply to a write and X.
4267 ****************************************************************************/
4268
4269 void reply_write_and_X(struct smb_request *req)
4270 {
4271         connection_struct *conn = req->conn;
4272         files_struct *fsp;
4273         struct lock_struct lock;
4274         SMB_OFF_T startpos;
4275         size_t numtowrite;
4276         bool write_through;
4277         ssize_t nwritten;
4278         unsigned int smb_doff;
4279         unsigned int smblen;
4280         char *data;
4281         NTSTATUS status;
4282
4283         START_PROFILE(SMBwriteX);
4284
4285         if ((req->wct != 12) && (req->wct != 14)) {
4286                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4287                 END_PROFILE(SMBwriteX);
4288                 return;
4289         }
4290
4291         numtowrite = SVAL(req->vwv+10, 0);
4292         smb_doff = SVAL(req->vwv+11, 0);
4293         smblen = smb_len(req->inbuf);
4294
4295         if (req->unread_bytes > 0xFFFF ||
4296                         (smblen > smb_doff &&
4297                                 smblen - smb_doff > 0xFFFF)) {
4298                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4299         }
4300
4301         if (req->unread_bytes) {
4302                 /* Can't do a recvfile write on IPC$ */
4303                 if (IS_IPC(conn)) {
4304                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4305                         END_PROFILE(SMBwriteX);
4306                         return;
4307                 }
4308                 if (numtowrite != req->unread_bytes) {
4309                         reply_doserror(req, ERRDOS, ERRbadmem);
4310                         END_PROFILE(SMBwriteX);
4311                         return;
4312                 }
4313         } else {
4314                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4315                                 smb_doff + numtowrite > smblen) {
4316                         reply_doserror(req, ERRDOS, ERRbadmem);
4317                         END_PROFILE(SMBwriteX);
4318                         return;
4319                 }
4320         }
4321
4322         /* If it's an IPC, pass off the pipe handler. */
4323         if (IS_IPC(conn)) {
4324                 if (req->unread_bytes) {
4325                         reply_doserror(req, ERRDOS, ERRbadmem);
4326                         END_PROFILE(SMBwriteX);
4327                         return;
4328                 }
4329                 reply_pipe_write_and_X(req);
4330                 END_PROFILE(SMBwriteX);
4331                 return;
4332         }
4333
4334         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4335         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4336         write_through = BITSETW(req->vwv+7,0);
4337
4338         if (!check_fsp(conn, req, fsp)) {
4339                 END_PROFILE(SMBwriteX);
4340                 return;
4341         }
4342
4343         if (!CHECK_WRITE(fsp)) {
4344                 reply_doserror(req, ERRDOS, ERRbadaccess);
4345                 END_PROFILE(SMBwriteX);
4346                 return;
4347         }
4348
4349         data = smb_base(req->inbuf) + smb_doff;
4350
4351         if(req->wct == 14) {
4352 #ifdef LARGE_SMB_OFF_T
4353                 /*
4354                  * This is a large offset (64 bit) write.
4355                  */
4356                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4357
4358 #else /* !LARGE_SMB_OFF_T */
4359
4360                 /*
4361                  * Ensure we haven't been sent a >32 bit offset.
4362                  */
4363
4364                 if(IVAL(req->vwv+12, 0) != 0) {
4365                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4366                                  "used and we don't support 64 bit offsets.\n",
4367                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4368                         reply_doserror(req, ERRDOS, ERRbadaccess);
4369                         END_PROFILE(SMBwriteX);
4370                         return;
4371                 }
4372
4373 #endif /* LARGE_SMB_OFF_T */
4374         }
4375
4376         init_strict_lock_struct(fsp, (uint32)req->smbpid,
4377             (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4378             &lock);
4379
4380         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4381                 reply_doserror(req, ERRDOS, ERRlock);
4382                 END_PROFILE(SMBwriteX);
4383                 return;
4384         }
4385
4386         /* X/Open SMB protocol says that, unlike SMBwrite
4387         if the length is zero then NO truncation is
4388         done, just a write of zero. To truncate a file,
4389         use SMBwrite. */
4390
4391         if(numtowrite == 0) {
4392                 nwritten = 0;
4393         } else {
4394
4395                 if ((req->unread_bytes == 0) &&
4396                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4397                                              numtowrite)) {
4398                         goto strict_unlock;
4399                 }
4400
4401                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4402         }
4403
4404         if(nwritten < 0) {
4405                 reply_nterror(req, map_nt_error_from_unix(errno));
4406                 goto strict_unlock;
4407         }
4408
4409         if((nwritten == 0) && (numtowrite != 0)) {
4410                 reply_doserror(req, ERRHRD, ERRdiskfull);
4411                 goto strict_unlock;
4412         }
4413
4414         reply_outbuf(req, 6, 0);
4415         SSVAL(req->outbuf,smb_vwv2,nwritten);
4416         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4417
4418         if (nwritten < (ssize_t)numtowrite) {
4419                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4420                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4421         }
4422
4423         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4424                 fsp->fnum, (int)numtowrite, (int)nwritten));
4425
4426         status = sync_file(conn, fsp, write_through);
4427         if (!NT_STATUS_IS_OK(status)) {
4428                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4429                          fsp_str_dbg(fsp), nt_errstr(status)));
4430                 reply_nterror(req, status);
4431                 goto strict_unlock;
4432         }
4433
4434         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4435
4436         END_PROFILE(SMBwriteX);
4437         chain_reply(req);
4438         return;
4439
4440 strict_unlock:
4441         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4442
4443         END_PROFILE(SMBwriteX);
4444         return;
4445 }
4446
4447 /****************************************************************************
4448  Reply to a lseek.
4449 ****************************************************************************/
4450
4451 void reply_lseek(struct smb_request *req)
4452 {
4453         connection_struct *conn = req->conn;
4454         SMB_OFF_T startpos;
4455         SMB_OFF_T res= -1;
4456         int mode,umode;
4457         files_struct *fsp;
4458
4459         START_PROFILE(SMBlseek);
4460
4461         if (req->wct < 4) {
4462                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4463                 END_PROFILE(SMBlseek);
4464                 return;
4465         }
4466
4467         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4468
4469         if (!check_fsp(conn, req, fsp)) {
4470                 return;
4471         }
4472
4473         flush_write_cache(fsp, SEEK_FLUSH);
4474
4475         mode = SVAL(req->vwv+1, 0) & 3;
4476         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4477         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4478
4479         switch (mode) {
4480                 case 0:
4481                         umode = SEEK_SET;
4482                         res = startpos;
4483                         break;
4484                 case 1:
4485                         umode = SEEK_CUR;
4486                         res = fsp->fh->pos + startpos;
4487                         break;
4488                 case 2:
4489                         umode = SEEK_END;
4490                         break;
4491                 default:
4492                         umode = SEEK_SET;
4493                         res = startpos;
4494                         break;
4495         }
4496
4497         if (umode == SEEK_END) {
4498                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4499                         if(errno == EINVAL) {
4500                                 SMB_OFF_T current_pos = startpos;
4501
4502                                 if(fsp_stat(fsp) == -1) {
4503                                         reply_nterror(req,
4504                                                 map_nt_error_from_unix(errno));
4505                                         END_PROFILE(SMBlseek);
4506                                         return;
4507                                 }
4508
4509                                 current_pos += fsp->fsp_name->st.st_ex_size;
4510                                 if(current_pos < 0)
4511                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4512                         }
4513                 }
4514
4515                 if(res == -1) {
4516                         reply_nterror(req, map_nt_error_from_unix(errno));
4517                         END_PROFILE(SMBlseek);
4518                         return;
4519                 }
4520         }
4521
4522         fsp->fh->pos = res;
4523
4524         reply_outbuf(req, 2, 0);
4525         SIVAL(req->outbuf,smb_vwv0,res);
4526
4527         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4528                 fsp->fnum, (double)startpos, (double)res, mode));
4529
4530         END_PROFILE(SMBlseek);
4531         return;
4532 }
4533
4534 /****************************************************************************
4535  Reply to a flush.
4536 ****************************************************************************/
4537
4538 void reply_flush(struct smb_request *req)
4539 {
4540         connection_struct *conn = req->conn;
4541         uint16 fnum;
4542         files_struct *fsp;
4543
4544         START_PROFILE(SMBflush);
4545
4546         if (req->wct < 1) {
4547                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4548                 return;
4549         }
4550
4551         fnum = SVAL(req->vwv+0, 0);
4552         fsp = file_fsp(req, fnum);
4553
4554         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4555                 return;
4556         }
4557
4558         if (!fsp) {
4559                 file_sync_all(conn);
4560         } else {
4561                 NTSTATUS status = sync_file(conn, fsp, True);
4562                 if (!NT_STATUS_IS_OK(status)) {
4563                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4564                                 fsp_str_dbg(fsp), nt_errstr(status)));
4565                         reply_nterror(req, status);
4566                         END_PROFILE(SMBflush);
4567                         return;
4568                 }
4569         }
4570
4571         reply_outbuf(req, 0, 0);
4572
4573         DEBUG(3,("flush\n"));
4574         END_PROFILE(SMBflush);
4575         return;
4576 }
4577
4578 /****************************************************************************
4579  Reply to a exit.
4580  conn POINTER CAN BE NULL HERE !
4581 ****************************************************************************/
4582
4583 void reply_exit(struct smb_request *req)
4584 {
4585         START_PROFILE(SMBexit);
4586
4587         file_close_pid(req->smbpid, req->vuid);
4588
4589         reply_outbuf(req, 0, 0);
4590
4591         DEBUG(3,("exit\n"));
4592
4593         END_PROFILE(SMBexit);
4594         return;
4595 }
4596
4597 /****************************************************************************
4598  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4599 ****************************************************************************/
4600
4601 void reply_close(struct smb_request *req)
4602 {
4603         connection_struct *conn = req->conn;
4604         NTSTATUS status = NT_STATUS_OK;
4605         files_struct *fsp = NULL;
4606         START_PROFILE(SMBclose);
4607
4608         if (req->wct < 3) {
4609                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4610                 END_PROFILE(SMBclose);
4611                 return;
4612         }
4613
4614         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4615
4616         /*
4617          * We can only use check_fsp if we know it's not a directory.
4618          */
4619
4620         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4621                 reply_doserror(req, ERRDOS, ERRbadfid);
4622                 END_PROFILE(SMBclose);
4623                 return;
4624         }
4625
4626         if(fsp->is_directory) {
4627                 /*
4628                  * Special case - close NT SMB directory handle.
4629                  */
4630                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4631                 status = close_file(req, fsp, NORMAL_CLOSE);
4632         } else {
4633                 time_t t;
4634                 /*
4635                  * Close ordinary file.
4636                  */
4637
4638                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4639                          fsp->fh->fd, fsp->fnum,
4640                          conn->num_files_open));
4641
4642                 /*
4643                  * Take care of any time sent in the close.
4644                  */
4645
4646                 t = srv_make_unix_date3(req->vwv+1);
4647                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4648
4649                 /*
4650                  * close_file() returns the unix errno if an error
4651                  * was detected on close - normally this is due to
4652                  * a disk full error. If not then it was probably an I/O error.
4653                  */
4654
4655                 status = close_file(req, fsp, NORMAL_CLOSE);
4656         }  
4657
4658         if (!NT_STATUS_IS_OK(status)) {
4659                 reply_nterror(req, status);
4660                 END_PROFILE(SMBclose);
4661                 return;
4662         }
4663
4664         reply_outbuf(req, 0, 0);
4665         END_PROFILE(SMBclose);
4666         return;
4667 }
4668
4669 /****************************************************************************
4670  Reply to a writeclose (Core+ protocol).
4671 ****************************************************************************/
4672
4673 void reply_writeclose(struct smb_request *req)
4674 {
4675         connection_struct *conn = req->conn;
4676         size_t numtowrite;
4677         ssize_t nwritten = -1;
4678         NTSTATUS close_status = NT_STATUS_OK;
4679         SMB_OFF_T startpos;
4680         const char *data;
4681         struct timespec mtime;
4682         files_struct *fsp;
4683         struct lock_struct lock;
4684
4685         START_PROFILE(SMBwriteclose);
4686
4687         if (req->wct < 6) {
4688                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4689                 END_PROFILE(SMBwriteclose);
4690                 return;
4691         }
4692
4693         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4694
4695         if (!check_fsp(conn, req, fsp)) {
4696                 END_PROFILE(SMBwriteclose);
4697                 return;
4698         }
4699         if (!CHECK_WRITE(fsp)) {
4700                 reply_doserror(req, ERRDOS,ERRbadaccess);
4701                 END_PROFILE(SMBwriteclose);
4702                 return;
4703         }
4704
4705         numtowrite = SVAL(req->vwv+1, 0);
4706         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4707         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4708         data = (const char *)req->buf + 1;
4709
4710         if (numtowrite) {
4711                 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4712                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4713                     &lock);
4714
4715                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4716                         reply_doserror(req, ERRDOS,ERRlock);
4717                         END_PROFILE(SMBwriteclose);
4718                         return;
4719                 }
4720         }
4721
4722         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4723
4724         set_close_write_time(fsp, mtime);
4725
4726         /*
4727          * More insanity. W2K only closes the file if writelen > 0.
4728          * JRA.
4729          */
4730
4731         if (numtowrite) {
4732                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4733                          "file %s\n", fsp_str_dbg(fsp)));
4734                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4735         }
4736
4737         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4738                  fsp->fnum, (int)numtowrite, (int)nwritten,
4739                  conn->num_files_open));
4740
4741         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4742                 reply_doserror(req, ERRHRD, ERRdiskfull);
4743                 goto strict_unlock;
4744         }
4745
4746         if(!NT_STATUS_IS_OK(close_status)) {
4747                 reply_nterror(req, close_status);
4748                 goto strict_unlock;
4749         }
4750
4751         reply_outbuf(req, 1, 0);
4752
4753         SSVAL(req->outbuf,smb_vwv0,nwritten);
4754
4755 strict_unlock:
4756         if (numtowrite) {
4757                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4758         }
4759
4760         END_PROFILE(SMBwriteclose);
4761         return;
4762 }
4763
4764 #undef DBGC_CLASS
4765 #define DBGC_CLASS DBGC_LOCKING
4766
4767 /****************************************************************************
4768  Reply to a lock.
4769 ****************************************************************************/
4770
4771 void reply_lock(struct smb_request *req)
4772 {
4773         connection_struct *conn = req->conn;
4774         uint64_t count,offset;
4775         NTSTATUS status;
4776         files_struct *fsp;
4777         struct byte_range_lock *br_lck = NULL;
4778
4779         START_PROFILE(SMBlock);
4780
4781         if (req->wct < 5) {
4782                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783                 END_PROFILE(SMBlock);
4784                 return;
4785         }
4786
4787         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4788
4789         if (!check_fsp(conn, req, fsp)) {
4790                 END_PROFILE(SMBlock);
4791                 return;
4792         }
4793
4794         count = (uint64_t)IVAL(req->vwv+1, 0);
4795         offset = (uint64_t)IVAL(req->vwv+3, 0);
4796
4797         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4798                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4799
4800         br_lck = do_lock(smbd_messaging_context(),
4801                         fsp,
4802                         req->smbpid,
4803                         count,
4804                         offset,
4805                         WRITE_LOCK,
4806                         WINDOWS_LOCK,
4807                         False, /* Non-blocking lock. */
4808                         &status,
4809                         NULL,
4810                         NULL);
4811
4812         TALLOC_FREE(br_lck);
4813
4814         if (NT_STATUS_V(status)) {
4815                 reply_nterror(req, status);
4816                 END_PROFILE(SMBlock);
4817                 return;
4818         }
4819
4820         reply_outbuf(req, 0, 0);
4821
4822         END_PROFILE(SMBlock);
4823         return;
4824 }
4825
4826 /****************************************************************************
4827  Reply to a unlock.
4828 ****************************************************************************/
4829
4830 void reply_unlock(struct smb_request *req)
4831 {
4832         connection_struct *conn = req->conn;
4833         uint64_t count,offset;
4834         NTSTATUS status;
4835         files_struct *fsp;
4836
4837         START_PROFILE(SMBunlock);
4838
4839         if (req->wct < 5) {
4840                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4841                 END_PROFILE(SMBunlock);
4842                 return;
4843         }
4844
4845         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4846
4847         if (!check_fsp(conn, req, fsp)) {
4848                 END_PROFILE(SMBunlock);
4849                 return;
4850         }
4851
4852         count = (uint64_t)IVAL(req->vwv+1, 0);
4853         offset = (uint64_t)IVAL(req->vwv+3, 0);
4854
4855         status = do_unlock(smbd_messaging_context(),
4856                         fsp,
4857                         req->smbpid,
4858                         count,
4859                         offset,
4860                         WINDOWS_LOCK);
4861
4862         if (NT_STATUS_V(status)) {
4863                 reply_nterror(req, status);
4864                 END_PROFILE(SMBunlock);
4865                 return;
4866         }
4867
4868         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4869                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4870
4871         reply_outbuf(req, 0, 0);
4872
4873         END_PROFILE(SMBunlock);
4874         return;
4875 }
4876
4877 #undef DBGC_CLASS
4878 #define DBGC_CLASS DBGC_ALL
4879
4880 /****************************************************************************
4881  Reply to a tdis.
4882  conn POINTER CAN BE NULL HERE !
4883 ****************************************************************************/
4884
4885 void reply_tdis(struct smb_request *req)
4886 {
4887         connection_struct *conn = req->conn;
4888         START_PROFILE(SMBtdis);
4889
4890         if (!conn) {
4891                 DEBUG(4,("Invalid connection in tdis\n"));
4892                 reply_doserror(req, ERRSRV, ERRinvnid);
4893                 END_PROFILE(SMBtdis);
4894                 return;
4895         }
4896
4897         conn->used = False;
4898
4899         close_cnum(conn,req->vuid);
4900         req->conn = NULL;
4901
4902         reply_outbuf(req, 0, 0);
4903         END_PROFILE(SMBtdis);
4904         return;
4905 }
4906
4907 /****************************************************************************
4908  Reply to a echo.
4909  conn POINTER CAN BE NULL HERE !
4910 ****************************************************************************/
4911
4912 void reply_echo(struct smb_request *req)
4913 {
4914         connection_struct *conn = req->conn;
4915         struct smb_perfcount_data local_pcd;
4916         struct smb_perfcount_data *cur_pcd;
4917         int smb_reverb;
4918         int seq_num;
4919
4920         START_PROFILE(SMBecho);
4921
4922         smb_init_perfcount_data(&local_pcd);
4923
4924         if (req->wct < 1) {
4925                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4926                 END_PROFILE(SMBecho);
4927                 return;
4928         }
4929
4930         smb_reverb = SVAL(req->vwv+0, 0);
4931
4932         reply_outbuf(req, 1, req->buflen);
4933
4934         /* copy any incoming data back out */
4935         if (req->buflen > 0) {
4936                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4937         }
4938
4939         if (smb_reverb > 100) {
4940                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4941                 smb_reverb = 100;
4942         }
4943
4944         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4945
4946                 /* this makes sure we catch the request pcd */
4947                 if (seq_num == smb_reverb) {
4948                         cur_pcd = &req->pcd;
4949                 } else {
4950                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4951                         cur_pcd = &local_pcd;
4952                 }
4953
4954                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4955
4956                 show_msg((char *)req->outbuf);
4957                 if (!srv_send_smb(smbd_server_fd(),
4958                                 (char *)req->outbuf,
4959                                 true, req->seqnum+1,
4960                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4961                                 cur_pcd))
4962                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4963         }
4964
4965         DEBUG(3,("echo %d times\n", smb_reverb));
4966
4967         TALLOC_FREE(req->outbuf);
4968
4969         END_PROFILE(SMBecho);
4970         return;
4971 }
4972
4973 /****************************************************************************
4974  Reply to a printopen.
4975 ****************************************************************************/
4976
4977 void reply_printopen(struct smb_request *req)
4978 {
4979         connection_struct *conn = req->conn;
4980         files_struct *fsp;
4981         NTSTATUS status;
4982
4983         START_PROFILE(SMBsplopen);
4984
4985         if (req->wct < 2) {
4986                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987                 END_PROFILE(SMBsplopen);
4988                 return;
4989         }
4990
4991         if (!CAN_PRINT(conn)) {
4992                 reply_doserror(req, ERRDOS, ERRnoaccess);
4993                 END_PROFILE(SMBsplopen);
4994                 return;
4995         }
4996
4997         status = file_new(req, conn, &fsp);
4998         if(!NT_STATUS_IS_OK(status)) {
4999                 reply_nterror(req, status);
5000                 END_PROFILE(SMBsplopen);
5001                 return;
5002         }
5003
5004         /* Open for exclusive use, write only. */
5005         status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5006
5007         if (!NT_STATUS_IS_OK(status)) {
5008                 file_free(req, fsp);
5009                 reply_nterror(req, status);
5010                 END_PROFILE(SMBsplopen);
5011                 return;
5012         }
5013
5014         reply_outbuf(req, 1, 0);
5015         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5016
5017         DEBUG(3,("openprint fd=%d fnum=%d\n",
5018                  fsp->fh->fd, fsp->fnum));
5019
5020         END_PROFILE(SMBsplopen);
5021         return;
5022 }
5023
5024 /****************************************************************************
5025  Reply to a printclose.
5026 ****************************************************************************/
5027
5028 void reply_printclose(struct smb_request *req)
5029 {
5030         connection_struct *conn = req->conn;
5031         files_struct *fsp;
5032         NTSTATUS status;
5033
5034         START_PROFILE(SMBsplclose);
5035
5036         if (req->wct < 1) {
5037                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5038                 END_PROFILE(SMBsplclose);
5039                 return;
5040         }
5041
5042         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5043
5044         if (!check_fsp(conn, req, fsp)) {
5045                 END_PROFILE(SMBsplclose);
5046                 return;
5047         }
5048
5049         if (!CAN_PRINT(conn)) {
5050                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5051                 END_PROFILE(SMBsplclose);
5052                 return;
5053         }
5054
5055         DEBUG(3,("printclose fd=%d fnum=%d\n",
5056                  fsp->fh->fd,fsp->fnum));
5057
5058         status = close_file(req, fsp, NORMAL_CLOSE);
5059
5060         if(!NT_STATUS_IS_OK(status)) {
5061                 reply_nterror(req, status);
5062                 END_PROFILE(SMBsplclose);
5063                 return;
5064         }
5065
5066         reply_outbuf(req, 0, 0);
5067
5068         END_PROFILE(SMBsplclose);
5069         return;
5070 }
5071
5072 /****************************************************************************
5073  Reply to a printqueue.
5074 ****************************************************************************/
5075
5076 void reply_printqueue(struct smb_request *req)
5077 {
5078         connection_struct *conn = req->conn;
5079         int max_count;
5080         int start_index;
5081
5082         START_PROFILE(SMBsplretq);
5083
5084         if (req->wct < 2) {
5085                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5086                 END_PROFILE(SMBsplretq);
5087                 return;
5088         }
5089
5090         max_count = SVAL(req->vwv+0, 0);
5091         start_index = SVAL(req->vwv+1, 0);
5092
5093         /* we used to allow the client to get the cnum wrong, but that
5094            is really quite gross and only worked when there was only
5095            one printer - I think we should now only accept it if they
5096            get it right (tridge) */
5097         if (!CAN_PRINT(conn)) {
5098                 reply_doserror(req, ERRDOS, ERRnoaccess);
5099                 END_PROFILE(SMBsplretq);
5100                 return;
5101         }
5102
5103         reply_outbuf(req, 2, 3);
5104         SSVAL(req->outbuf,smb_vwv0,0);
5105         SSVAL(req->outbuf,smb_vwv1,0);
5106         SCVAL(smb_buf(req->outbuf),0,1);
5107         SSVAL(smb_buf(req->outbuf),1,0);
5108
5109         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5110                  start_index, max_count));
5111
5112         {
5113                 print_queue_struct *queue = NULL;
5114                 print_status_struct status;
5115                 int count = print_queue_status(SNUM(conn), &queue, &status);
5116                 int num_to_get = ABS(max_count);
5117                 int first = (max_count>0?start_index:start_index+max_count+1);
5118                 int i;
5119
5120                 if (first >= count)
5121                         num_to_get = 0;
5122                 else
5123                         num_to_get = MIN(num_to_get,count-first);
5124
5125
5126                 for (i=first;i<first+num_to_get;i++) {
5127                         char blob[28];
5128                         char *p = blob;
5129
5130                         srv_put_dos_date2(p,0,queue[i].time);
5131                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5132                         SSVAL(p,5, queue[i].job);
5133                         SIVAL(p,7,queue[i].size);
5134                         SCVAL(p,11,0);
5135                         srvstr_push(blob, req->flags2, p+12,
5136                                     queue[i].fs_user, 16, STR_ASCII);
5137
5138                         if (message_push_blob(
5139                                     &req->outbuf,
5140                                     data_blob_const(
5141                                             blob, sizeof(blob))) == -1) {
5142                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5143                                 END_PROFILE(SMBsplretq);
5144                                 return;
5145                         }
5146                 }
5147
5148                 if (count > 0) {
5149                         SSVAL(req->outbuf,smb_vwv0,count);
5150                         SSVAL(req->outbuf,smb_vwv1,
5151                               (max_count>0?first+count:first-1));
5152                         SCVAL(smb_buf(req->outbuf),0,1);
5153                         SSVAL(smb_buf(req->outbuf),1,28*count);
5154                 }
5155
5156                 SAFE_FREE(queue);
5157
5158                 DEBUG(3,("%d entries returned in queue\n",count));
5159         }
5160
5161         END_PROFILE(SMBsplretq);
5162         return;
5163 }
5164
5165 /****************************************************************************
5166  Reply to a printwrite.
5167 ****************************************************************************/
5168
5169 void reply_printwrite(struct smb_request *req)
5170 {
5171         connection_struct *conn = req->conn;
5172         int numtowrite;
5173         const char *data;
5174         files_struct *fsp;
5175
5176         START_PROFILE(SMBsplwr);
5177
5178         if (req->wct < 1) {
5179                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5180                 END_PROFILE(SMBsplwr);
5181                 return;
5182         }
5183
5184         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5185
5186         if (!check_fsp(conn, req, fsp)) {
5187                 END_PROFILE(SMBsplwr);
5188                 return;
5189         }
5190
5191         if (!CAN_PRINT(conn)) {
5192                 reply_doserror(req, ERRDOS, ERRnoaccess);
5193                 END_PROFILE(SMBsplwr);
5194                 return;
5195         }
5196
5197         if (!CHECK_WRITE(fsp)) {
5198                 reply_doserror(req, ERRDOS, ERRbadaccess);
5199                 END_PROFILE(SMBsplwr);
5200                 return;
5201         }
5202
5203         numtowrite = SVAL(req->buf, 1);
5204
5205         if (req->buflen < numtowrite + 3) {
5206                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5207                 END_PROFILE(SMBsplwr);
5208                 return;
5209         }
5210
5211         data = (const char *)req->buf + 3;
5212
5213         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5214                 reply_nterror(req, map_nt_error_from_unix(errno));
5215                 END_PROFILE(SMBsplwr);
5216                 return;
5217         }
5218
5219         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5220
5221         END_PROFILE(SMBsplwr);
5222         return;
5223 }
5224
5225 /****************************************************************************
5226  Reply to a mkdir.
5227 ****************************************************************************/
5228
5229 void reply_mkdir(struct smb_request *req)
5230 {
5231         connection_struct *conn = req->conn;
5232         struct smb_filename *smb_dname = NULL;
5233         char *directory = NULL;
5234         NTSTATUS status;
5235         TALLOC_CTX *ctx = talloc_tos();
5236
5237         START_PROFILE(SMBmkdir);
5238
5239         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5240                             STR_TERMINATE, &status);
5241         if (!NT_STATUS_IS_OK(status)) {
5242                 reply_nterror(req, status);
5243                 goto out;
5244         }
5245
5246         status = filename_convert(ctx, conn,
5247                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5248                                  directory,
5249                                  0,
5250                                  NULL,
5251                                  &smb_dname);
5252         if (!NT_STATUS_IS_OK(status)) {
5253                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5254                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5255                                         ERRSRV, ERRbadpath);
5256                         goto out;
5257                 }
5258                 reply_nterror(req, status);
5259                 goto out;
5260         }
5261
5262         status = create_directory(conn, req, smb_dname);
5263
5264         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5265
5266         if (!NT_STATUS_IS_OK(status)) {
5267
5268                 if (!use_nt_status()
5269                     && NT_STATUS_EQUAL(status,
5270                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5271                         /*
5272                          * Yes, in the DOS error code case we get a
5273                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5274                          * samba4 torture test.
5275                          */
5276                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5277                 }
5278
5279                 reply_nterror(req, status);
5280                 goto out;
5281         }
5282
5283         reply_outbuf(req, 0, 0);
5284
5285         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5286  out:
5287         TALLOC_FREE(smb_dname);
5288         END_PROFILE(SMBmkdir);
5289         return;
5290 }
5291
5292 /****************************************************************************
5293  Static function used by reply_rmdir to delete an entire directory
5294  tree recursively. Return True on ok, False on fail.
5295 ****************************************************************************/
5296
5297 static bool recursive_rmdir(TALLOC_CTX *ctx,
5298                         connection_struct *conn,
5299                         struct smb_filename *smb_dname)
5300 {
5301         char *dname = NULL;
5302         bool ret = True;
5303         long offset = 0;
5304         SMB_STRUCT_STAT st;
5305         struct smb_Dir *dir_hnd;
5306
5307         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5308
5309         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5310         if(dir_hnd == NULL)
5311                 return False;
5312
5313         while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5314                 struct smb_filename *smb_dname_full = NULL;
5315                 char *fullname = NULL;
5316                 bool do_break = true;
5317                 NTSTATUS status;
5318
5319                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5320                         TALLOC_FREE(dname);
5321                         continue;
5322                 }
5323
5324                 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5325                                      false)) {
5326                         TALLOC_FREE(dname);
5327                         continue;
5328                 }
5329
5330                 /* Construct the full name. */
5331                 fullname = talloc_asprintf(ctx,
5332                                 "%s/%s",
5333                                 smb_dname->base_name,
5334                                 dname);
5335                 if (!fullname) {
5336                         errno = ENOMEM;
5337                         goto err_break;
5338                 }
5339
5340                 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5341                                                     NULL, NULL,
5342                                                     &smb_dname_full);
5343                 if (!NT_STATUS_IS_OK(status)) {
5344                         goto err_break;
5345                 }
5346
5347                 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5348                         goto err_break;
5349                 }
5350
5351                 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5352                         if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5353                                 goto err_break;
5354                         }
5355                         if(SMB_VFS_RMDIR(conn,
5356                                          smb_dname_full->base_name) != 0) {
5357                                 goto err_break;
5358                         }
5359                 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5360                         goto err_break;
5361                 }
5362
5363                 /* Successful iteration. */
5364                 do_break = false;
5365
5366          err_break:
5367                 TALLOC_FREE(smb_dname_full);
5368                 TALLOC_FREE(fullname);
5369                 TALLOC_FREE(dname);
5370                 if (do_break) {
5371                         ret = false;
5372                         break;
5373                 }
5374         }
5375         TALLOC_FREE(dir_hnd);
5376         return ret;
5377 }
5378
5379 /****************************************************************************
5380  The internals of the rmdir code - called elsewhere.
5381 ****************************************************************************/
5382
5383 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5384                          connection_struct *conn,
5385                          struct smb_filename *smb_dname)
5386 {
5387         int ret;
5388
5389         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5390
5391         /* Might be a symlink. */
5392         if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5393                 return map_nt_error_from_unix(errno);
5394         }
5395
5396         if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5397                 /* Is what it points to a directory ? */
5398                 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5399                         return map_nt_error_from_unix(errno);
5400                 }
5401                 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5402                         return NT_STATUS_NOT_A_DIRECTORY;
5403                 }
5404                 ret = SMB_VFS_UNLINK(conn, smb_dname);
5405         } else {
5406                 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5407         }
5408         if (ret == 0) {
5409                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5410                              FILE_NOTIFY_CHANGE_DIR_NAME,
5411                              smb_dname->base_name);
5412                 return NT_STATUS_OK;
5413         }
5414
5415         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5416                 /*
5417                  * Check to see if the only thing in this directory are
5418                  * vetoed files/directories. If so then delete them and
5419                  * retry. If we fail to delete any of them (and we *don't*
5420                  * do a recursive delete) then fail the rmdir.
5421                  */
5422                 SMB_STRUCT_STAT st;
5423                 char *dname = NULL;
5424                 long dirpos = 0;
5425                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5426                                                   smb_dname->base_name, NULL,
5427                                                   0);
5428
5429                 if(dir_hnd == NULL) {
5430                         errno = ENOTEMPTY;
5431                         goto err;
5432                 }
5433
5434                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5435                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
5436                                 TALLOC_FREE(dname);
5437                                 continue;
5438                         }
5439                         if (!is_visible_file(conn, smb_dname->base_name, dname,
5440                                              &st, false)) {
5441                                 TALLOC_FREE(dname);
5442                                 continue;
5443                         }
5444                         if(!IS_VETO_PATH(conn, dname)) {
5445                                 TALLOC_FREE(dir_hnd);
5446                                 TALLOC_FREE(dname);
5447                                 errno = ENOTEMPTY;
5448                                 goto err;
5449                         }
5450                         TALLOC_FREE(dname);
5451                 }
5452
5453                 /* We only have veto files/directories.
5454                  * Are we allowed to delete them ? */
5455
5456                 if(!lp_recursive_veto_delete(SNUM(conn))) {
5457                         TALLOC_FREE(dir_hnd);
5458                         errno = ENOTEMPTY;
5459                         goto err;
5460                 }
5461
5462                 /* Do a recursive delete. */
5463                 RewindDir(dir_hnd,&dirpos);
5464                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5465                         struct smb_filename *smb_dname_full = NULL;
5466                         char *fullname = NULL;
5467                         bool do_break = true;
5468                         NTSTATUS status;
5469
5470                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5471                                 TALLOC_FREE(dname);
5472                                 continue;
5473                         }
5474                         if (!is_visible_file(conn, smb_dname->base_name, dname,
5475                                              &st, false)) {
5476                                 TALLOC_FREE(dname);
5477                                 continue;
5478                         }
5479
5480                         fullname = talloc_asprintf(ctx,
5481                                         "%s/%s",
5482                                         smb_dname->base_name,
5483                                         dname);
5484
5485                         if(!fullname) {
5486                                 errno = ENOMEM;
5487                                 goto err_break;
5488                         }
5489
5490                         status = create_synthetic_smb_fname(talloc_tos(),
5491                                                             fullname, NULL,
5492                                                             NULL,
5493                                                             &smb_dname_full);
5494                         if (!NT_STATUS_IS_OK(status)) {
5495                                 errno = map_errno_from_nt_status(status);
5496                                 goto err_break;
5497                         }
5498
5499                         if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5500                                 goto err_break;
5501                         }
5502                         if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5503                                 if(!recursive_rmdir(ctx, conn,
5504                                                     smb_dname_full)) {
5505                                         goto err_break;
5506                                 }
5507                                 if(SMB_VFS_RMDIR(conn,
5508                                         smb_dname_full->base_name) != 0) {
5509                                         goto err_break;
5510                                 }
5511                         } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5512                                 goto err_break;
5513                         }
5514
5515                         /* Successful iteration. */
5516                         do_break = false;
5517
5518                  err_break:
5519                         TALLOC_FREE(fullname);
5520                         TALLOC_FREE(smb_dname_full);
5521                         TALLOC_FREE(dname);
5522                         if (do_break)
5523                                 break;
5524                 }
5525                 TALLOC_FREE(dir_hnd);
5526                 /* Retry the rmdir */
5527                 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5528         }
5529
5530   err:
5531
5532         if (ret != 0) {
5533                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5534                          "%s\n", smb_fname_str_dbg(smb_dname),
5535                          strerror(errno)));
5536                 return map_nt_error_from_unix(errno);
5537         }
5538
5539         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5540                      FILE_NOTIFY_CHANGE_DIR_NAME,
5541                      smb_dname->base_name);
5542
5543         return NT_STATUS_OK;
5544 }
5545
5546 /****************************************************************************
5547  Reply to a rmdir.
5548 ****************************************************************************/
5549
5550 void reply_rmdir(struct smb_request *req)
5551 {
5552         connection_struct *conn = req->conn;
5553         struct smb_filename *smb_dname = NULL;
5554         char *directory = NULL;
5555         NTSTATUS status;
5556         TALLOC_CTX *ctx = talloc_tos();
5557         struct smbd_server_connection *sconn = smbd_server_conn;
5558
5559         START_PROFILE(SMBrmdir);
5560
5561         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5562                             STR_TERMINATE, &status);
5563         if (!NT_STATUS_IS_OK(status)) {
5564                 reply_nterror(req, status);
5565                 goto out;
5566         }
5567
5568         status = filename_convert(ctx, conn,
5569                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5570                                  directory,
5571                                  0,
5572                                  NULL,
5573                                  &smb_dname);
5574         if (!NT_STATUS_IS_OK(status)) {
5575                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5576                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5577                                         ERRSRV, ERRbadpath);
5578                         goto out;
5579                 }
5580                 reply_nterror(req, status);
5581                 goto out;
5582         }
5583
5584         if (is_ntfs_stream_smb_fname(smb_dname)) {
5585                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5586                 goto out;
5587         }
5588
5589         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5590         status = rmdir_internals(ctx, conn, smb_dname);
5591         if (!NT_STATUS_IS_OK(status)) {
5592                 reply_nterror(req, status);
5593                 goto out;
5594         }
5595
5596         reply_outbuf(req, 0, 0);
5597
5598         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5599  out:
5600         TALLOC_FREE(smb_dname);
5601         END_PROFILE(SMBrmdir);
5602         return;
5603 }
5604
5605 /*******************************************************************
5606  Resolve wildcards in a filename rename.
5607 ********************************************************************/
5608
5609 static bool resolve_wildcards(TALLOC_CTX *ctx,
5610                                 const char *name1,
5611                                 const char *name2,
5612                                 char **pp_newname)
5613 {
5614         char *name2_copy = NULL;
5615         char *root1 = NULL;
5616         char *root2 = NULL;
5617         char *ext1 = NULL;
5618         char *ext2 = NULL;
5619         char *p,*p2, *pname1, *pname2;
5620
5621         name2_copy = talloc_strdup(ctx, name2);
5622         if (!name2_copy) {
5623                 return False;
5624         }
5625
5626         pname1 = strrchr_m(name1,'/');
5627         pname2 = strrchr_m(name2_copy,'/');
5628
5629         if (!pname1 || !pname2) {
5630                 return False;
5631         }
5632
5633         /* Truncate the copy of name2 at the last '/' */
5634         *pname2 = '\0';
5635
5636         /* Now go past the '/' */
5637         pname1++;
5638         pname2++;
5639
5640         root1 = talloc_strdup(ctx, pname1);
5641         root2 = talloc_strdup(ctx, pname2);
5642
5643         if (!root1 || !root2) {
5644                 return False;
5645         }
5646
5647         p = strrchr_m(root1,'.');
5648         if (p) {
5649                 *p = 0;
5650                 ext1 = talloc_strdup(ctx, p+1);
5651         } else {
5652                 ext1 = talloc_strdup(ctx, "");
5653         }
5654         p = strrchr_m(root2,'.');
5655         if (p) {
5656                 *p = 0;
5657                 ext2 = talloc_strdup(ctx, p+1);
5658         } else {
5659                 ext2 = talloc_strdup(ctx, "");
5660         }
5661
5662         if (!ext1 || !ext2) {
5663                 return False;
5664         }
5665
5666         p = root1;
5667         p2 = root2;
5668         while (*p2) {
5669                 if (*p2 == '?') {
5670                         /* Hmmm. Should this be mb-aware ? */
5671                         *p2 = *p;
5672                         p2++;
5673                 } else if (*p2 == '*') {
5674                         *p2 = '\0';
5675                         root2 = talloc_asprintf(ctx, "%s%s",
5676                                                 root2,
5677                                                 p);
5678                         if (!root2) {
5679                                 return False;
5680                         }
5681                         break;
5682                 } else {
5683                         p2++;
5684                 }
5685                 if (*p) {
5686                         p++;
5687                 }
5688         }
5689
5690         p = ext1;
5691         p2 = ext2;
5692         while (*p2) {
5693                 if (*p2 == '?') {
5694                         /* Hmmm. Should this be mb-aware ? */
5695                         *p2 = *p;
5696                         p2++;
5697                 } else if (*p2 == '*') {
5698                         *p2 = '\0';
5699                         ext2 = talloc_asprintf(ctx, "%s%s",
5700                                                 ext2,
5701                                                 p);
5702                         if (!ext2) {
5703                                 return False;
5704                         }
5705                         break;
5706                 } else {
5707                         p2++;
5708                 }
5709                 if (*p) {
5710                         p++;
5711                 }
5712         }
5713
5714         if (*ext2) {
5715                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5716                                 name2_copy,
5717                                 root2,
5718                                 ext2);
5719         } else {
5720                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5721                                 name2_copy,
5722                                 root2);
5723         }
5724
5725         if (!*pp_newname) {
5726                 return False;
5727         }
5728
5729         return True;
5730 }
5731
5732 /****************************************************************************
5733  Ensure open files have their names updated. Updated to notify other smbd's
5734  asynchronously.
5735 ****************************************************************************/
5736
5737 static void rename_open_files(connection_struct *conn,
5738                               struct share_mode_lock *lck,
5739                               const struct smb_filename *smb_fname_dst)
5740 {
5741         files_struct *fsp;
5742         bool did_rename = False;
5743         NTSTATUS status;
5744
5745         for(fsp = file_find_di_first(lck->id); fsp;
5746             fsp = file_find_di_next(fsp)) {
5747                 /* fsp_name is a relative path under the fsp. To change this for other
5748                    sharepaths we need to manipulate relative paths. */
5749                 /* TODO - create the absolute path and manipulate the newname
5750                    relative to the sharepath. */
5751                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5752                         continue;
5753                 }
5754                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5755                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5756                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5757                            smb_fname_str_dbg(smb_fname_dst)));
5758
5759                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5760                 if (NT_STATUS_IS_OK(status)) {
5761                         did_rename = True;
5762                 }
5763         }
5764
5765         if (!did_rename) {
5766                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5767                            "for %s\n", file_id_string_tos(&lck->id),
5768                            smb_fname_str_dbg(smb_fname_dst)));
5769         }
5770
5771         /* Send messages to all smbd's (not ourself) that the name has changed. */
5772         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5773                               smb_fname_dst);
5774
5775 }
5776
5777 /****************************************************************************
5778  We need to check if the source path is a parent directory of the destination
5779  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5780  refuse the rename with a sharing violation. Under UNIX the above call can
5781  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5782  probably need to check that the client is a Windows one before disallowing
5783  this as a UNIX client (one with UNIX extensions) can know the source is a
5784  symlink and make this decision intelligently. Found by an excellent bug
5785  report from <AndyLiebman@aol.com>.
5786 ****************************************************************************/
5787
5788 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5789                                      const struct smb_filename *smb_fname_dst)
5790 {
5791         const char *psrc = smb_fname_src->base_name;
5792         const char *pdst = smb_fname_dst->base_name;
5793         size_t slen;
5794
5795         if (psrc[0] == '.' && psrc[1] == '/') {
5796                 psrc += 2;
5797         }
5798         if (pdst[0] == '.' && pdst[1] == '/') {
5799                 pdst += 2;
5800         }
5801         if ((slen = strlen(psrc)) > strlen(pdst)) {
5802                 return False;
5803         }
5804         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5805 }
5806
5807 /*
5808  * Do the notify calls from a rename
5809  */
5810
5811 static void notify_rename(connection_struct *conn, bool is_dir,
5812                           const struct smb_filename *smb_fname_src,
5813                           const struct smb_filename *smb_fname_dst)
5814 {
5815         char *parent_dir_src = NULL;
5816         char *parent_dir_dst = NULL;
5817         uint32 mask;
5818
5819         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5820                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5821
5822         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5823                             &parent_dir_src, NULL) ||
5824             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5825                             &parent_dir_dst, NULL)) {
5826                 goto out;
5827         }
5828
5829         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5830                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5831                              smb_fname_src->base_name);
5832                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5833                              smb_fname_dst->base_name);
5834         }
5835         else {
5836                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5837                              smb_fname_src->base_name);
5838                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5839                              smb_fname_dst->base_name);
5840         }
5841
5842         /* this is a strange one. w2k3 gives an additional event for
5843            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5844            files, but not directories */
5845         if (!is_dir) {
5846                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5847                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5848                              |FILE_NOTIFY_CHANGE_CREATION,
5849                              smb_fname_dst->base_name);
5850         }
5851  out:
5852         TALLOC_FREE(parent_dir_src);
5853         TALLOC_FREE(parent_dir_dst);
5854 }
5855
5856 /****************************************************************************
5857  Rename an open file - given an fsp.
5858 ****************************************************************************/
5859
5860 NTSTATUS rename_internals_fsp(connection_struct *conn,
5861                         files_struct *fsp,
5862                         const struct smb_filename *smb_fname_dst_in,
5863                         uint32 attrs,
5864                         bool replace_if_exists)
5865 {
5866         TALLOC_CTX *ctx = talloc_tos();
5867         struct smb_filename *smb_fname_dst = NULL;
5868         NTSTATUS status = NT_STATUS_OK;
5869         struct share_mode_lock *lck = NULL;
5870         bool dst_exists, old_is_stream, new_is_stream;
5871
5872         status = check_name(conn, smb_fname_dst_in->base_name);
5873         if (!NT_STATUS_IS_OK(status)) {
5874                 return status;
5875         }
5876
5877         /* Make a copy of the dst smb_fname structs */
5878
5879         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5880         if (!NT_STATUS_IS_OK(status)) {
5881                 goto out;
5882         }
5883
5884         /* Ensure the dst smb_fname contains a '/' */
5885         if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5886                 char * tmp;
5887                 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5888                                       smb_fname_dst->base_name);
5889                 if (!tmp) {
5890                         status = NT_STATUS_NO_MEMORY;
5891                         goto out;
5892                 }
5893                 TALLOC_FREE(smb_fname_dst->base_name);
5894                 smb_fname_dst->base_name = tmp;
5895         }
5896
5897         /*
5898          * Check for special case with case preserving and not
5899          * case sensitive. If the old last component differs from the original
5900          * last component only by case, then we should allow
5901          * the rename (user is trying to change the case of the
5902          * filename).
5903          */
5904         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5905             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5906             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5907                 char *last_slash;
5908                 char *fname_dst_lcomp_base_mod = NULL;
5909                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5910
5911                 /*
5912                  * Get the last component of the destination name.  Note that
5913                  * we guarantee that destination name contains a '/' character
5914                  * above.
5915                  */
5916                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5917                 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5918                 if (!fname_dst_lcomp_base_mod) {
5919                         status = NT_STATUS_NO_MEMORY;
5920                         goto out;
5921                 }
5922
5923                 /*
5924                  * Create an smb_filename struct using the original last
5925                  * component of the destination.
5926                  */
5927                 status = create_synthetic_smb_fname_split(ctx,
5928                     smb_fname_dst->original_lcomp, NULL,
5929                     &smb_fname_orig_lcomp);
5930                 if (!NT_STATUS_IS_OK(status)) {
5931                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5932                         goto out;
5933                 }
5934
5935                 /* If the base names only differ by case, use original. */
5936                 if(!strcsequal(fname_dst_lcomp_base_mod,
5937                                smb_fname_orig_lcomp->base_name)) {
5938                         char *tmp;
5939                         /*
5940                          * Replace the modified last component with the
5941                          * original.
5942                          */
5943                         *last_slash = '\0'; /* Truncate at the '/' */
5944                         tmp = talloc_asprintf(smb_fname_dst,
5945                                         "%s/%s",
5946                                         smb_fname_dst->base_name,
5947                                         smb_fname_orig_lcomp->base_name);
5948                         if (tmp == NULL) {
5949                                 status = NT_STATUS_NO_MEMORY;
5950                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5951                                 TALLOC_FREE(smb_fname_orig_lcomp);
5952                                 goto out;
5953                         }
5954                         TALLOC_FREE(smb_fname_dst->base_name);
5955                         smb_fname_dst->base_name = tmp;
5956                 }
5957
5958                 /* If the stream_names only differ by case, use original. */
5959                 if(!strcsequal(smb_fname_dst->stream_name,
5960                                smb_fname_orig_lcomp->stream_name)) {
5961                         char *tmp = NULL;
5962                         /* Use the original stream. */
5963                         tmp = talloc_strdup(smb_fname_dst,
5964                                             smb_fname_orig_lcomp->stream_name);
5965                         if (tmp == NULL) {
5966                                 status = NT_STATUS_NO_MEMORY;
5967                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5968                                 TALLOC_FREE(smb_fname_orig_lcomp);
5969                                 goto out;
5970                         }
5971                         TALLOC_FREE(smb_fname_dst->stream_name);
5972                         smb_fname_dst->stream_name = tmp;
5973                 }
5974                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5975                 TALLOC_FREE(smb_fname_orig_lcomp);
5976         }
5977
5978         /*
5979          * If the src and dest names are identical - including case,
5980          * don't do the rename, just return success.
5981          */
5982
5983         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5984             strcsequal(fsp->fsp_name->stream_name,
5985                        smb_fname_dst->stream_name)) {
5986                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5987                           "- returning success\n",
5988                           smb_fname_str_dbg(smb_fname_dst)));
5989                 status = NT_STATUS_OK;
5990                 goto out;
5991         }
5992
5993         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5994         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5995
5996         /* Return the correct error code if both names aren't streams. */
5997         if (!old_is_stream && new_is_stream) {
5998                 status = NT_STATUS_OBJECT_NAME_INVALID;
5999                 goto out;
6000         }
6001
6002         if (old_is_stream && !new_is_stream) {
6003                 status = NT_STATUS_INVALID_PARAMETER;
6004                 goto out;
6005         }
6006
6007         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6008
6009         if(!replace_if_exists && dst_exists) {
6010                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6011                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6012                           smb_fname_str_dbg(smb_fname_dst)));
6013                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6014                 goto out;
6015         }
6016
6017         if (dst_exists) {
6018                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6019                     &smb_fname_dst->st);
6020                 files_struct *dst_fsp = file_find_di_first(fileid);
6021                 /* The file can be open when renaming a stream */
6022                 if (dst_fsp && !new_is_stream) {
6023                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6024                         status = NT_STATUS_ACCESS_DENIED;
6025                         goto out;
6026                 }
6027         }
6028
6029         /* Ensure we have a valid stat struct for the source. */
6030         status = vfs_stat_fsp(fsp);
6031         if (!NT_STATUS_IS_OK(status)) {
6032                 goto out;
6033         }
6034
6035         status = can_rename(conn, fsp, attrs);
6036
6037         if (!NT_STATUS_IS_OK(status)) {
6038                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6039                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6040                           smb_fname_str_dbg(smb_fname_dst)));
6041                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6042                         status = NT_STATUS_ACCESS_DENIED;
6043                 goto out;
6044         }
6045
6046         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6047                 status = NT_STATUS_ACCESS_DENIED;
6048         }
6049
6050         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6051                                   NULL);
6052
6053         /*
6054          * We have the file open ourselves, so not being able to get the
6055          * corresponding share mode lock is a fatal error.
6056          */
6057
6058         SMB_ASSERT(lck != NULL);
6059
6060         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6061                 uint32 create_options = fsp->fh->private_options;
6062
6063                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6064                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6065                           smb_fname_str_dbg(smb_fname_dst)));
6066
6067                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6068                               smb_fname_dst);
6069
6070                 rename_open_files(conn, lck, smb_fname_dst);
6071
6072                 /*
6073                  * A rename acts as a new file create w.r.t. allowing an initial delete
6074                  * on close, probably because in Windows there is a new handle to the
6075                  * new file. If initial delete on close was requested but not
6076                  * originally set, we need to set it here. This is probably not 100% correct,
6077                  * but will work for the CIFSFS client which in non-posix mode
6078                  * depends on these semantics. JRA.
6079                  */
6080
6081                 if (create_options & FILE_DELETE_ON_CLOSE) {
6082                         status = can_set_delete_on_close(fsp, True, 0);
6083
6084                         if (NT_STATUS_IS_OK(status)) {
6085                                 /* Note that here we set the *inital* delete on close flag,
6086                                  * not the regular one. The magic gets handled in close. */
6087                                 fsp->initial_delete_on_close = True;
6088                         }
6089                 }
6090                 TALLOC_FREE(lck);
6091                 status = NT_STATUS_OK;
6092                 goto out;
6093         }
6094
6095         TALLOC_FREE(lck);
6096
6097         if (errno == ENOTDIR || errno == EISDIR) {
6098                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6099         } else {
6100                 status = map_nt_error_from_unix(errno);
6101         }
6102
6103         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6104                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6105                   smb_fname_str_dbg(smb_fname_dst)));
6106
6107  out:
6108         TALLOC_FREE(smb_fname_dst);
6109
6110         return status;
6111 }
6112
6113 /****************************************************************************
6114  The guts of the rename command, split out so it may be called by the NT SMB
6115  code.
6116 ****************************************************************************/
6117
6118 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6119                         connection_struct *conn,
6120                         struct smb_request *req,
6121                         struct smb_filename *smb_fname_src,
6122                         struct smb_filename *smb_fname_dst,
6123                         uint32 attrs,
6124                         bool replace_if_exists,
6125                         bool src_has_wild,
6126                         bool dest_has_wild,
6127                         uint32_t access_mask)
6128 {
6129         char *fname_src_dir = NULL;
6130         char *fname_src_mask = NULL;
6131         int count=0;
6132         NTSTATUS status = NT_STATUS_OK;
6133         struct smb_Dir *dir_hnd = NULL;
6134         char *dname = NULL;
6135         long offset = 0;
6136         int create_options = 0;
6137         bool posix_pathnames = lp_posix_pathnames();
6138
6139         /*
6140          * Split the old name into directory and last component
6141          * strings. Note that unix_convert may have stripped off a
6142          * leading ./ from both name and newname if the rename is
6143          * at the root of the share. We need to make sure either both
6144          * name and newname contain a / character or neither of them do
6145          * as this is checked in resolve_wildcards().
6146          */
6147
6148         /* Split up the directory from the filename/mask. */
6149         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6150                                       &fname_src_dir, &fname_src_mask);
6151         if (!NT_STATUS_IS_OK(status)) {
6152                 status = NT_STATUS_NO_MEMORY;
6153                 goto out;
6154         }
6155
6156         /*
6157          * We should only check the mangled cache
6158          * here if unix_convert failed. This means
6159          * that the path in 'mask' doesn't exist
6160          * on the file system and so we need to look
6161          * for a possible mangle. This patch from
6162          * Tine Smukavec <valentin.smukavec@hermes.si>.
6163          */
6164
6165         if (!VALID_STAT(smb_fname_src->st) &&
6166             mangle_is_mangled(fname_src_mask, conn->params)) {
6167                 char *new_mask = NULL;
6168                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6169                                             conn->params);
6170                 if (new_mask) {
6171                         TALLOC_FREE(fname_src_mask);
6172                         fname_src_mask = new_mask;
6173                 }
6174         }
6175
6176         if (!src_has_wild) {
6177                 files_struct *fsp;
6178
6179                 /*
6180                  * Only one file needs to be renamed. Append the mask back
6181                  * onto the directory.
6182                  */
6183                 TALLOC_FREE(smb_fname_src->base_name);
6184                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6185                                                            "%s/%s",
6186                                                            fname_src_dir,
6187                                                            fname_src_mask);
6188                 if (!smb_fname_src->base_name) {
6189                         status = NT_STATUS_NO_MEMORY;
6190                         goto out;
6191                 }
6192
6193                 /* Ensure dst fname contains a '/' also */
6194                 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6195                         char *tmp;
6196                         tmp = talloc_asprintf(smb_fname_dst, "./%s",
6197                                               smb_fname_dst->base_name);
6198                         if (!tmp) {
6199                                 status = NT_STATUS_NO_MEMORY;
6200                                 goto out;
6201                         }
6202                         TALLOC_FREE(smb_fname_dst->base_name);
6203                         smb_fname_dst->base_name = tmp;
6204                 }
6205
6206                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6207                           "case_preserve = %d, short case preserve = %d, "
6208                           "directory = %s, newname = %s, "
6209                           "last_component_dest = %s\n",
6210                           conn->case_sensitive, conn->case_preserve,
6211                           conn->short_case_preserve,
6212                           smb_fname_str_dbg(smb_fname_src),
6213                           smb_fname_str_dbg(smb_fname_dst),
6214                           smb_fname_dst->original_lcomp));
6215
6216                 /* The dest name still may have wildcards. */
6217                 if (dest_has_wild) {
6218                         char *fname_dst_mod = NULL;
6219                         if (!resolve_wildcards(smb_fname_dst,
6220                                                smb_fname_src->base_name,
6221                                                smb_fname_dst->base_name,
6222                                                &fname_dst_mod)) {
6223                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6224                                           "%s %s failed\n",
6225                                           smb_fname_src->base_name,
6226                                           smb_fname_dst->base_name));
6227                                 status = NT_STATUS_NO_MEMORY;
6228                                 goto out;
6229                         }
6230                         TALLOC_FREE(smb_fname_dst->base_name);
6231                         smb_fname_dst->base_name = fname_dst_mod;
6232                 }
6233
6234                 ZERO_STRUCT(smb_fname_src->st);
6235                 if (posix_pathnames) {
6236                         SMB_VFS_LSTAT(conn, smb_fname_src);
6237                 } else {
6238                         SMB_VFS_STAT(conn, smb_fname_src);
6239                 }
6240
6241                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6242                         create_options |= FILE_DIRECTORY_FILE;
6243                 }
6244
6245                 status = SMB_VFS_CREATE_FILE(
6246                         conn,                           /* conn */
6247                         req,                            /* req */
6248                         0,                              /* root_dir_fid */
6249                         smb_fname_src,                  /* fname */
6250                         access_mask,                    /* access_mask */
6251                         (FILE_SHARE_READ |              /* share_access */
6252                             FILE_SHARE_WRITE),
6253                         FILE_OPEN,                      /* create_disposition*/
6254                         create_options,                 /* create_options */
6255                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6256                         0,                              /* oplock_request */
6257                         0,                              /* allocation_size */
6258                         NULL,                           /* sd */
6259                         NULL,                           /* ea_list */
6260                         &fsp,                           /* result */
6261                         NULL);                          /* pinfo */
6262
6263                 if (!NT_STATUS_IS_OK(status)) {
6264                         DEBUG(3, ("Could not open rename source %s: %s\n",
6265                                   smb_fname_str_dbg(smb_fname_src),
6266                                   nt_errstr(status)));
6267                         goto out;
6268                 }
6269
6270                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6271                                               attrs, replace_if_exists);
6272
6273                 close_file(req, fsp, NORMAL_CLOSE);
6274
6275                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6276                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6277                           smb_fname_str_dbg(smb_fname_dst)));
6278
6279                 goto out;
6280         }
6281
6282         /*
6283          * Wildcards - process each file that matches.
6284          */
6285         if (strequal(fname_src_mask, "????????.???")) {
6286                 TALLOC_FREE(fname_src_mask);
6287                 fname_src_mask = talloc_strdup(ctx, "*");
6288                 if (!fname_src_mask) {
6289                         status = NT_STATUS_NO_MEMORY;
6290                         goto out;
6291                 }
6292         }
6293
6294         status = check_name(conn, fname_src_dir);
6295         if (!NT_STATUS_IS_OK(status)) {
6296                 goto out;
6297         }
6298
6299         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6300                           attrs);
6301         if (dir_hnd == NULL) {
6302                 status = map_nt_error_from_unix(errno);
6303                 goto out;
6304         }
6305
6306         status = NT_STATUS_NO_SUCH_FILE;
6307         /*
6308          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6309          * - gentest fix. JRA
6310          */
6311
6312         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6313                 files_struct *fsp = NULL;
6314                 char *destname = NULL;
6315                 bool sysdir_entry = False;
6316
6317                 /* Quick check for "." and ".." */
6318                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6319                         if (attrs & aDIR) {
6320                                 sysdir_entry = True;
6321                         } else {
6322                                 TALLOC_FREE(dname);
6323                                 continue;
6324                         }
6325                 }
6326
6327                 if (!is_visible_file(conn, fname_src_dir, dname,
6328                                      &smb_fname_src->st, false)) {
6329                         TALLOC_FREE(dname);
6330                         continue;
6331                 }
6332
6333                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6334                         TALLOC_FREE(dname);
6335                         continue;
6336                 }
6337
6338                 if (sysdir_entry) {
6339                         status = NT_STATUS_OBJECT_NAME_INVALID;
6340                         break;
6341                 }
6342
6343                 TALLOC_FREE(smb_fname_src->base_name);
6344                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6345                                                            "%s/%s",
6346                                                            fname_src_dir,
6347                                                            dname);
6348                 if (!smb_fname_src->base_name) {
6349                         status = NT_STATUS_NO_MEMORY;
6350                         goto out;
6351                 }
6352
6353                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6354                                        smb_fname_dst->base_name,
6355                                        &destname)) {
6356                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6357                                   smb_fname_src->base_name, destname));
6358                         TALLOC_FREE(dname);
6359                         continue;
6360                 }
6361                 if (!destname) {
6362                         status = NT_STATUS_NO_MEMORY;
6363                         goto out;
6364                 }
6365
6366                 TALLOC_FREE(smb_fname_dst->base_name);
6367                 smb_fname_dst->base_name = destname;
6368
6369                 ZERO_STRUCT(smb_fname_src->st);
6370                 if (posix_pathnames) {
6371                         SMB_VFS_LSTAT(conn, smb_fname_src);
6372                 } else {
6373                         SMB_VFS_STAT(conn, smb_fname_src);
6374                 }
6375
6376                 create_options = 0;
6377
6378                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6379                         create_options |= FILE_DIRECTORY_FILE;
6380                 }
6381
6382                 status = SMB_VFS_CREATE_FILE(
6383                         conn,                           /* conn */
6384                         req,                            /* req */
6385                         0,                              /* root_dir_fid */
6386                         smb_fname_src,                  /* fname */
6387                         access_mask,                    /* access_mask */
6388                         (FILE_SHARE_READ |              /* share_access */
6389                             FILE_SHARE_WRITE),
6390                         FILE_OPEN,                      /* create_disposition*/
6391                         create_options,                 /* create_options */
6392                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6393                         0,                              /* oplock_request */
6394                         0,                              /* allocation_size */
6395                         NULL,                           /* sd */
6396                         NULL,                           /* ea_list */
6397                         &fsp,                           /* result */
6398                         NULL);                          /* pinfo */
6399
6400                 if (!NT_STATUS_IS_OK(status)) {
6401                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6402                                  "returned %s rename %s -> %s\n",
6403                                  nt_errstr(status),
6404                                  smb_fname_str_dbg(smb_fname_src),
6405                                  smb_fname_str_dbg(smb_fname_dst)));
6406                         break;
6407                 }
6408
6409                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6410                                                               dname);
6411                 if (!smb_fname_dst->original_lcomp) {
6412                         status = NT_STATUS_NO_MEMORY;
6413                         goto out;
6414                 }
6415
6416                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6417                                               attrs, replace_if_exists);
6418
6419                 close_file(req, fsp, NORMAL_CLOSE);
6420
6421                 if (!NT_STATUS_IS_OK(status)) {
6422                         DEBUG(3, ("rename_internals_fsp returned %s for "
6423                                   "rename %s -> %s\n", nt_errstr(status),
6424                                   smb_fname_str_dbg(smb_fname_src),
6425                                   smb_fname_str_dbg(smb_fname_dst)));
6426                         break;
6427                 }
6428
6429                 count++;
6430
6431                 DEBUG(3,("rename_internals: doing rename on %s -> "
6432                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6433                          smb_fname_str_dbg(smb_fname_src)));
6434                 TALLOC_FREE(dname);
6435         }
6436         TALLOC_FREE(dir_hnd);
6437
6438         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6439                 status = map_nt_error_from_unix(errno);
6440         }
6441
6442  out:
6443         TALLOC_FREE(dname);
6444         TALLOC_FREE(fname_src_dir);
6445         TALLOC_FREE(fname_src_mask);
6446         return status;
6447 }
6448
6449 /****************************************************************************
6450  Reply to a mv.
6451 ****************************************************************************/
6452
6453 void reply_mv(struct smb_request *req)
6454 {
6455         connection_struct *conn = req->conn;
6456         char *name = NULL;
6457         char *newname = NULL;
6458         const char *p;
6459         uint32 attrs;
6460         NTSTATUS status;
6461         bool src_has_wcard = False;
6462         bool dest_has_wcard = False;
6463         TALLOC_CTX *ctx = talloc_tos();
6464         struct smb_filename *smb_fname_src = NULL;
6465         struct smb_filename *smb_fname_dst = NULL;
6466
6467         START_PROFILE(SMBmv);
6468
6469         if (req->wct < 1) {
6470                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6471                 goto out;
6472         }
6473
6474         attrs = SVAL(req->vwv+0, 0);
6475
6476         p = (const char *)req->buf + 1;
6477         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6478                                        &status, &src_has_wcard);
6479         if (!NT_STATUS_IS_OK(status)) {
6480                 reply_nterror(req, status);
6481                 goto out;
6482         }
6483         p++;
6484         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6485                                        &status, &dest_has_wcard);
6486         if (!NT_STATUS_IS_OK(status)) {
6487                 reply_nterror(req, status);
6488                 goto out;
6489         }
6490
6491         status = filename_convert(ctx,
6492                                   conn,
6493                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6494                                   name,
6495                                   UCF_COND_ALLOW_WCARD_LCOMP,
6496                                   &src_has_wcard,
6497                                   &smb_fname_src);
6498
6499         if (!NT_STATUS_IS_OK(status)) {
6500                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6501                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6502                                         ERRSRV, ERRbadpath);
6503                         goto out;
6504                 }
6505                 reply_nterror(req, status);
6506                 goto out;
6507         }
6508
6509         status = filename_convert(ctx,
6510                                   conn,
6511                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6512                                   newname,
6513                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6514                                   &dest_has_wcard,
6515                                   &smb_fname_dst);
6516
6517         if (!NT_STATUS_IS_OK(status)) {
6518                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6519                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6520                                         ERRSRV, ERRbadpath);
6521                         goto out;
6522                 }
6523                 reply_nterror(req, status);
6524                 goto out;
6525         }
6526
6527         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6528                  smb_fname_str_dbg(smb_fname_dst)));
6529
6530         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6531                                   attrs, False, src_has_wcard, dest_has_wcard,
6532                                   DELETE_ACCESS);
6533         if (!NT_STATUS_IS_OK(status)) {
6534                 if (open_was_deferred(req->mid)) {
6535                         /* We have re-scheduled this call. */
6536                         goto out;
6537                 }
6538                 reply_nterror(req, status);
6539                 goto out;
6540         }
6541
6542         reply_outbuf(req, 0, 0);
6543  out:
6544         TALLOC_FREE(smb_fname_src);
6545         TALLOC_FREE(smb_fname_dst);
6546         END_PROFILE(SMBmv);
6547         return;
6548 }
6549
6550 /*******************************************************************
6551  Copy a file as part of a reply_copy.
6552 ******************************************************************/
6553
6554 /*
6555  * TODO: check error codes on all callers
6556  */
6557
6558 NTSTATUS copy_file(TALLOC_CTX *ctx,
6559                         connection_struct *conn,
6560                         struct smb_filename *smb_fname_src,
6561                         struct smb_filename *smb_fname_dst,
6562                         int ofun,
6563                         int count,
6564                         bool target_is_directory)
6565 {
6566         struct smb_filename *smb_fname_dst_tmp = NULL;
6567         SMB_OFF_T ret=-1;
6568         files_struct *fsp1,*fsp2;
6569         uint32 dosattrs;
6570         uint32 new_create_disposition;
6571         NTSTATUS status;
6572
6573
6574         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6575         if (!NT_STATUS_IS_OK(status)) {
6576                 return status;
6577         }
6578
6579         /*
6580          * If the target is a directory, extract the last component from the
6581          * src filename and append it to the dst filename
6582          */
6583         if (target_is_directory) {
6584                 const char *p;
6585
6586                 /* dest/target can't be a stream if it's a directory. */
6587                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6588
6589                 p = strrchr_m(smb_fname_src->base_name,'/');
6590                 if (p) {
6591                         p++;
6592                 } else {
6593                         p = smb_fname_src->base_name;
6594                 }
6595                 smb_fname_dst_tmp->base_name =
6596                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6597                                            p);
6598                 if (!smb_fname_dst_tmp->base_name) {
6599                         status = NT_STATUS_NO_MEMORY;
6600                         goto out;
6601                 }
6602         }
6603
6604         status = vfs_file_exist(conn, smb_fname_src);
6605         if (!NT_STATUS_IS_OK(status)) {
6606                 goto out;
6607         }
6608
6609         if (!target_is_directory && count) {
6610                 new_create_disposition = FILE_OPEN;
6611         } else {
6612                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6613                                                  NULL, NULL,
6614                                                  &new_create_disposition,
6615                                                  NULL)) {
6616                         status = NT_STATUS_INVALID_PARAMETER;
6617                         goto out;
6618                 }
6619         }
6620
6621         /* Open the src file for reading. */
6622         status = SMB_VFS_CREATE_FILE(
6623                 conn,                                   /* conn */
6624                 NULL,                                   /* req */
6625                 0,                                      /* root_dir_fid */
6626                 smb_fname_src,                          /* fname */
6627                 FILE_GENERIC_READ,                      /* access_mask */
6628                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6629                 FILE_OPEN,                              /* create_disposition*/
6630                 0,                                      /* create_options */
6631                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6632                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6633                 0,                                      /* allocation_size */
6634                 NULL,                                   /* sd */
6635                 NULL,                                   /* ea_list */
6636                 &fsp1,                                  /* result */
6637                 NULL);                                  /* psbuf */
6638
6639         if (!NT_STATUS_IS_OK(status)) {
6640                 goto out;
6641         }
6642
6643         dosattrs = dos_mode(conn, smb_fname_src);
6644
6645         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6646                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6647         }
6648
6649         /* Open the dst file for writing. */
6650         status = SMB_VFS_CREATE_FILE(
6651                 conn,                                   /* conn */
6652                 NULL,                                   /* req */
6653                 0,                                      /* root_dir_fid */
6654                 smb_fname_dst,                          /* fname */
6655                 FILE_GENERIC_WRITE,                     /* access_mask */
6656                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6657                 new_create_disposition,                 /* create_disposition*/
6658                 0,                                      /* create_options */
6659                 dosattrs,                               /* file_attributes */
6660                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6661                 0,                                      /* allocation_size */
6662                 NULL,                                   /* sd */
6663                 NULL,                                   /* ea_list */
6664                 &fsp2,                                  /* result */
6665                 NULL);                                  /* psbuf */
6666
6667         if (!NT_STATUS_IS_OK(status)) {
6668                 close_file(NULL, fsp1, ERROR_CLOSE);
6669                 goto out;
6670         }
6671
6672         if ((ofun&3) == 1) {
6673                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6674                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6675                         /*
6676                          * Stop the copy from occurring.
6677                          */
6678                         ret = -1;
6679                         smb_fname_src->st.st_ex_size = 0;
6680                 }
6681         }
6682
6683         /* Do the actual copy. */
6684         if (smb_fname_src->st.st_ex_size) {
6685                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6686         }
6687
6688         close_file(NULL, fsp1, NORMAL_CLOSE);
6689
6690         /* Ensure the modtime is set correctly on the destination file. */
6691         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6692
6693         /*
6694          * As we are opening fsp1 read-only we only expect
6695          * an error on close on fsp2 if we are out of space.
6696          * Thus we don't look at the error return from the
6697          * close of fsp1.
6698          */
6699         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6700
6701         if (!NT_STATUS_IS_OK(status)) {
6702                 goto out;
6703         }
6704
6705         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6706                 status = NT_STATUS_DISK_FULL;
6707                 goto out;
6708         }
6709
6710         status = NT_STATUS_OK;
6711
6712  out:
6713         TALLOC_FREE(smb_fname_dst_tmp);
6714         return status;
6715 }
6716
6717 /****************************************************************************
6718  Reply to a file copy.
6719 ****************************************************************************/
6720
6721 void reply_copy(struct smb_request *req)
6722 {
6723         connection_struct *conn = req->conn;
6724         struct smb_filename *smb_fname_src = NULL;
6725         struct smb_filename *smb_fname_dst = NULL;
6726         char *fname_src = NULL;
6727         char *fname_dst = NULL;
6728         char *fname_src_mask = NULL;
6729         char *fname_src_dir = NULL;
6730         const char *p;
6731         int count=0;
6732         int error = ERRnoaccess;
6733         int tid2;
6734         int ofun;
6735         int flags;
6736         bool target_is_directory=False;
6737         bool source_has_wild = False;
6738         bool dest_has_wild = False;
6739         NTSTATUS status;
6740         TALLOC_CTX *ctx = talloc_tos();
6741
6742         START_PROFILE(SMBcopy);
6743
6744         if (req->wct < 3) {
6745                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6746                 goto out;
6747         }
6748
6749         tid2 = SVAL(req->vwv+0, 0);
6750         ofun = SVAL(req->vwv+1, 0);
6751         flags = SVAL(req->vwv+2, 0);
6752
6753         p = (const char *)req->buf;
6754         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6755                                        &status, &source_has_wild);
6756         if (!NT_STATUS_IS_OK(status)) {
6757                 reply_nterror(req, status);
6758                 goto out;
6759         }
6760         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6761                                        &status, &dest_has_wild);
6762         if (!NT_STATUS_IS_OK(status)) {
6763                 reply_nterror(req, status);
6764                 goto out;
6765         }
6766
6767         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6768
6769         if (tid2 != conn->cnum) {
6770                 /* can't currently handle inter share copies XXXX */
6771                 DEBUG(3,("Rejecting inter-share copy\n"));
6772                 reply_doserror(req, ERRSRV, ERRinvdevice);
6773                 goto out;
6774         }
6775
6776         status = filename_convert(ctx, conn,
6777                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6778                                   fname_src,
6779                                   UCF_COND_ALLOW_WCARD_LCOMP,
6780                                   &source_has_wild,
6781                                   &smb_fname_src);
6782         if (!NT_STATUS_IS_OK(status)) {
6783                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6784                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6785                                         ERRSRV, ERRbadpath);
6786                         goto out;
6787                 }
6788                 reply_nterror(req, status);
6789                 goto out;
6790         }
6791
6792         status = filename_convert(ctx, conn,
6793                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6794                                   fname_dst,
6795                                   UCF_COND_ALLOW_WCARD_LCOMP,
6796                                   &dest_has_wild,
6797                                   &smb_fname_dst);
6798         if (!NT_STATUS_IS_OK(status)) {
6799                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6800                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6801                                         ERRSRV, ERRbadpath);
6802                         goto out;
6803                 }
6804                 reply_nterror(req, status);
6805                 goto out;
6806         }
6807
6808         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6809
6810         if ((flags&1) && target_is_directory) {
6811                 reply_doserror(req, ERRDOS, ERRbadfile);
6812                 goto out;
6813         }
6814
6815         if ((flags&2) && !target_is_directory) {
6816                 reply_doserror(req, ERRDOS, ERRbadpath);
6817                 goto out;
6818         }
6819
6820         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6821                 /* wants a tree copy! XXXX */
6822                 DEBUG(3,("Rejecting tree copy\n"));
6823                 reply_doserror(req, ERRSRV, ERRerror);
6824                 goto out;
6825         }
6826
6827         /* Split up the directory from the filename/mask. */
6828         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6829                                       &fname_src_dir, &fname_src_mask);
6830         if (!NT_STATUS_IS_OK(status)) {
6831                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6832                 goto out;
6833         }
6834
6835         /*
6836          * We should only check the mangled cache
6837          * here if unix_convert failed. This means
6838          * that the path in 'mask' doesn't exist
6839          * on the file system and so we need to look
6840          * for a possible mangle. This patch from
6841          * Tine Smukavec <valentin.smukavec@hermes.si>.
6842          */
6843         if (!VALID_STAT(smb_fname_src->st) &&
6844             mangle_is_mangled(fname_src_mask, conn->params)) {
6845                 char *new_mask = NULL;
6846                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6847                                             &new_mask, conn->params);
6848
6849                 /* Use demangled name if one was successfully found. */
6850                 if (new_mask) {
6851                         TALLOC_FREE(fname_src_mask);
6852                         fname_src_mask = new_mask;
6853                 }
6854         }
6855
6856         if (!source_has_wild) {
6857
6858                 /*
6859                  * Only one file needs to be copied. Append the mask back onto
6860                  * the directory.
6861                  */
6862                 TALLOC_FREE(smb_fname_src->base_name);
6863                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6864                                                            "%s/%s",
6865                                                            fname_src_dir,
6866                                                            fname_src_mask);
6867                 if (!smb_fname_src->base_name) {
6868                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6869                         goto out;
6870                 }
6871
6872                 if (dest_has_wild) {
6873                         char *fname_dst_mod = NULL;
6874                         if (!resolve_wildcards(smb_fname_dst,
6875                                                smb_fname_src->base_name,
6876                                                smb_fname_dst->base_name,
6877                                                &fname_dst_mod)) {
6878                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6879                                 goto out;
6880                         }
6881                         TALLOC_FREE(smb_fname_dst->base_name);
6882                         smb_fname_dst->base_name = fname_dst_mod;
6883                 }
6884
6885                 status = check_name(conn, smb_fname_src->base_name);
6886                 if (!NT_STATUS_IS_OK(status)) {
6887                         reply_nterror(req, status);
6888                         goto out;
6889                 }
6890
6891                 status = check_name(conn, smb_fname_dst->base_name);
6892                 if (!NT_STATUS_IS_OK(status)) {
6893                         reply_nterror(req, status);
6894                         goto out;
6895                 }
6896
6897                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6898                                    ofun, count, target_is_directory);
6899
6900                 if(!NT_STATUS_IS_OK(status)) {
6901                         reply_nterror(req, status);
6902                         goto out;
6903                 } else {
6904                         count++;
6905                 }
6906         } else {
6907                 struct smb_Dir *dir_hnd = NULL;
6908                 char *dname = NULL;
6909                 long offset = 0;
6910
6911                 /*
6912                  * There is a wildcard that requires us to actually read the
6913                  * src dir and copy each file matching the mask to the dst.
6914                  * Right now streams won't be copied, but this could
6915                  * presumably be added with a nested loop for reach dir entry.
6916                  */
6917                 SMB_ASSERT(!smb_fname_src->stream_name);
6918                 SMB_ASSERT(!smb_fname_dst->stream_name);
6919
6920                 smb_fname_src->stream_name = NULL;
6921                 smb_fname_dst->stream_name = NULL;
6922
6923                 if (strequal(fname_src_mask,"????????.???")) {
6924                         TALLOC_FREE(fname_src_mask);
6925                         fname_src_mask = talloc_strdup(ctx, "*");
6926                         if (!fname_src_mask) {
6927                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6928                                 goto out;
6929                         }
6930                 }
6931
6932                 status = check_name(conn, fname_src_dir);
6933                 if (!NT_STATUS_IS_OK(status)) {
6934                         reply_nterror(req, status);
6935                         goto out;
6936                 }
6937
6938                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6939                 if (dir_hnd == NULL) {
6940                         status = map_nt_error_from_unix(errno);
6941                         reply_nterror(req, status);
6942                         goto out;
6943                 }
6944
6945                 error = ERRbadfile;
6946
6947                 /* Iterate over the src dir copying each entry to the dst. */
6948                 while ((dname = ReadDirName(dir_hnd, &offset,
6949                                             &smb_fname_src->st))) {
6950                         char *destname = NULL;
6951
6952                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6953                                 TALLOC_FREE(dname);
6954                                 continue;
6955                         }
6956
6957                         if (!is_visible_file(conn, fname_src_dir, dname,
6958                                              &smb_fname_src->st, false)) {
6959                                 TALLOC_FREE(dname);
6960                                 continue;
6961                         }
6962
6963                         if(!mask_match(dname, fname_src_mask,
6964                                        conn->case_sensitive)) {
6965                                 TALLOC_FREE(dname);
6966                                 continue;
6967                         }
6968
6969                         error = ERRnoaccess;
6970
6971                         /* Get the src smb_fname struct setup. */
6972                         TALLOC_FREE(smb_fname_src->base_name);
6973                         smb_fname_src->base_name =
6974                             talloc_asprintf(smb_fname_src, "%s/%s",
6975                                             fname_src_dir, dname);
6976
6977                         if (!smb_fname_src->base_name) {
6978                                 TALLOC_FREE(dir_hnd);
6979                                 TALLOC_FREE(dname);
6980                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6981                                 goto out;
6982                         }
6983
6984                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6985                                                smb_fname_dst->base_name,
6986                                                &destname)) {
6987                                 TALLOC_FREE(dname);
6988                                 continue;
6989                         }
6990                         if (!destname) {
6991                                 TALLOC_FREE(dir_hnd);
6992                                 TALLOC_FREE(dname);
6993                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6994                                 goto out;
6995                         }
6996
6997                         TALLOC_FREE(smb_fname_dst->base_name);
6998                         smb_fname_dst->base_name = destname;
6999
7000                         status = check_name(conn, smb_fname_src->base_name);
7001                         if (!NT_STATUS_IS_OK(status)) {
7002                                 TALLOC_FREE(dir_hnd);
7003                                 TALLOC_FREE(dname);
7004                                 reply_nterror(req, status);
7005                                 goto out;
7006                         }
7007
7008                         status = check_name(conn, smb_fname_dst->base_name);
7009                         if (!NT_STATUS_IS_OK(status)) {
7010                                 TALLOC_FREE(dir_hnd);
7011                                 TALLOC_FREE(dname);
7012                                 reply_nterror(req, status);
7013                                 goto out;
7014                         }
7015
7016                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7017                                 smb_fname_src->base_name,
7018                                 smb_fname_dst->base_name));
7019
7020                         status = copy_file(ctx, conn, smb_fname_src,
7021                                            smb_fname_dst, ofun, count,
7022                                            target_is_directory);
7023                         if (NT_STATUS_IS_OK(status)) {
7024                                 count++;
7025                         }
7026
7027                         TALLOC_FREE(dname);
7028                 }
7029                 TALLOC_FREE(dir_hnd);
7030         }
7031
7032         if (count == 0) {
7033                 reply_doserror(req, ERRDOS, error);
7034                 goto out;
7035         }
7036
7037         reply_outbuf(req, 1, 0);
7038         SSVAL(req->outbuf,smb_vwv0,count);
7039  out:
7040         TALLOC_FREE(smb_fname_src);
7041         TALLOC_FREE(smb_fname_dst);
7042         TALLOC_FREE(fname_src);
7043         TALLOC_FREE(fname_dst);
7044         TALLOC_FREE(fname_src_mask);
7045         TALLOC_FREE(fname_src_dir);
7046
7047         END_PROFILE(SMBcopy);
7048         return;
7049 }
7050
7051 #undef DBGC_CLASS
7052 #define DBGC_CLASS DBGC_LOCKING
7053
7054 /****************************************************************************
7055  Get a lock pid, dealing with large count requests.
7056 ****************************************************************************/
7057
7058 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7059                     bool large_file_format)
7060 {
7061         if(!large_file_format)
7062                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7063         else
7064                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7065 }
7066
7067 /****************************************************************************
7068  Get a lock count, dealing with large count requests.
7069 ****************************************************************************/
7070
7071 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7072                         bool large_file_format)
7073 {
7074         uint64_t count = 0;
7075
7076         if(!large_file_format) {
7077                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7078         } else {
7079
7080 #if defined(HAVE_LONGLONG)
7081                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7082                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7083 #else /* HAVE_LONGLONG */
7084
7085                 /*
7086                  * NT4.x seems to be broken in that it sends large file (64 bit)
7087                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7088                  * negotiated. For boxes without large unsigned ints truncate the
7089                  * lock count by dropping the top 32 bits.
7090                  */
7091
7092                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7093                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7094                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7095                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7096                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7097                 }
7098
7099                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7100 #endif /* HAVE_LONGLONG */
7101         }
7102
7103         return count;
7104 }
7105
7106 #if !defined(HAVE_LONGLONG)
7107 /****************************************************************************
7108  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7109 ****************************************************************************/
7110
7111 static uint32 map_lock_offset(uint32 high, uint32 low)
7112 {
7113         unsigned int i;
7114         uint32 mask = 0;
7115         uint32 highcopy = high;
7116
7117         /*
7118          * Try and find out how many significant bits there are in high.
7119          */
7120
7121         for(i = 0; highcopy; i++)
7122                 highcopy >>= 1;
7123
7124         /*
7125          * We use 31 bits not 32 here as POSIX
7126          * lock offsets may not be negative.
7127          */
7128
7129         mask = (~0) << (31 - i);
7130
7131         if(low & mask)
7132                 return 0; /* Fail. */
7133
7134         high <<= (31 - i);
7135
7136         return (high|low);
7137 }
7138 #endif /* !defined(HAVE_LONGLONG) */
7139
7140 /****************************************************************************
7141  Get a lock offset, dealing with large offset requests.
7142 ****************************************************************************/
7143
7144 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7145                          bool large_file_format, bool *err)
7146 {
7147         uint64_t offset = 0;
7148
7149         *err = False;
7150
7151         if(!large_file_format) {
7152                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7153         } else {
7154
7155 #if defined(HAVE_LONGLONG)
7156                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7157                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7158 #else /* HAVE_LONGLONG */
7159
7160                 /*
7161                  * NT4.x seems to be broken in that it sends large file (64 bit)
7162                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7163                  * negotiated. For boxes without large unsigned ints mangle the
7164                  * lock offset by mapping the top 32 bits onto the lower 32.
7165                  */
7166
7167                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7168                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7169                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7170                         uint32 new_low = 0;
7171
7172                         if((new_low = map_lock_offset(high, low)) == 0) {
7173                                 *err = True;
7174                                 return (uint64_t)-1;
7175                         }
7176
7177                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7178                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7179                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7180                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7181                 }
7182
7183                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7184 #endif /* HAVE_LONGLONG */
7185         }
7186
7187         return offset;
7188 }
7189
7190 NTSTATUS smbd_do_locking(struct smb_request *req,
7191                          files_struct *fsp,
7192                          uint8_t type,
7193                          int32_t timeout,
7194                          uint16_t num_ulocks,
7195                          struct smbd_lock_element *ulocks,
7196                          uint16_t num_locks,
7197                          struct smbd_lock_element *locks,
7198                          bool *async)
7199 {
7200         connection_struct *conn = req->conn;
7201         int i;
7202         NTSTATUS status = NT_STATUS_OK;
7203
7204         *async = false;
7205
7206         /* Data now points at the beginning of the list
7207            of smb_unlkrng structs */
7208         for(i = 0; i < (int)num_ulocks; i++) {
7209                 struct smbd_lock_element *e = &ulocks[i];
7210
7211                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7212                           "pid %u, file %s\n",
7213                           (double)e->offset,
7214                           (double)e->count,
7215                           (unsigned int)e->smbpid,
7216                           fsp_str_dbg(fsp)));
7217
7218                 if (e->brltype != UNLOCK_LOCK) {
7219                         /* this can only happen with SMB2 */
7220                         return NT_STATUS_INVALID_PARAMETER;
7221                 }
7222
7223                 status = do_unlock(smbd_messaging_context(),
7224                                 fsp,
7225                                 e->smbpid,
7226                                 e->count,
7227                                 e->offset,
7228                                 WINDOWS_LOCK);
7229
7230                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7231                     nt_errstr(status)));
7232
7233                 if (!NT_STATUS_IS_OK(status)) {
7234                         return status;
7235                 }
7236         }
7237
7238         /* Setup the timeout in seconds. */
7239
7240         if (!lp_blocking_locks(SNUM(conn))) {
7241                 timeout = 0;
7242         }
7243
7244         /* Data now points at the beginning of the list
7245            of smb_lkrng structs */
7246
7247         for(i = 0; i < (int)num_locks; i++) {
7248                 struct smbd_lock_element *e = &locks[i];
7249
7250                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7251                           "%u, file %s timeout = %d\n",
7252                           (double)e->offset,
7253                           (double)e->count,
7254                           (unsigned int)e->smbpid,
7255                           fsp_str_dbg(fsp),
7256                           (int)timeout));
7257
7258                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7259                         struct blocking_lock_record *blr = NULL;
7260
7261                         if (lp_blocking_locks(SNUM(conn))) {
7262
7263                                 /* Schedule a message to ourselves to
7264                                    remove the blocking lock record and
7265                                    return the right error. */
7266
7267                                 blr = blocking_lock_cancel(fsp,
7268                                                 e->smbpid,
7269                                                 e->offset,
7270                                                 e->count,
7271                                                 WINDOWS_LOCK,
7272                                                 type,
7273                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7274                                 if (blr == NULL) {
7275                                         return NT_STATUS_DOS(
7276                                                         ERRDOS,
7277                                                         ERRcancelviolation);
7278                                 }
7279                         }
7280                         /* Remove a matching pending lock. */
7281                         status = do_lock_cancel(fsp,
7282                                                 e->smbpid,
7283                                                 e->count,
7284                                                 e->offset,
7285                                                 WINDOWS_LOCK,
7286                                                 blr);
7287                 } else {
7288                         bool blocking_lock = timeout ? true : false;
7289                         bool defer_lock = false;
7290                         struct byte_range_lock *br_lck;
7291                         uint32_t block_smbpid;
7292
7293                         br_lck = do_lock(smbd_messaging_context(),
7294                                         fsp,
7295                                         e->smbpid,
7296                                         e->count,
7297                                         e->offset, 
7298                                         e->brltype,
7299                                         WINDOWS_LOCK,
7300                                         blocking_lock,
7301                                         &status,
7302                                         &block_smbpid,
7303                                         NULL);
7304
7305                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7306                                 /* Windows internal resolution for blocking locks seems
7307                                    to be about 200ms... Don't wait for less than that. JRA. */
7308                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7309                                         timeout = lp_lock_spin_time();
7310                                 }
7311                                 defer_lock = true;
7312                         }
7313
7314                         /* This heuristic seems to match W2K3 very well. If a
7315                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7316                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
7317                            far as I can tell. Replacement for do_lock_spin(). JRA. */
7318
7319                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7320                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7321                                 defer_lock = true;
7322                                 timeout = lp_lock_spin_time();
7323                         }
7324
7325                         if (br_lck && defer_lock) {
7326                                 /*
7327                                  * A blocking lock was requested. Package up
7328                                  * this smb into a queued request and push it
7329                                  * onto the blocking lock queue.
7330                                  */
7331                                 if(push_blocking_lock_request(br_lck,
7332                                                         req,
7333                                                         fsp,
7334                                                         timeout,
7335                                                         i,
7336                                                         e->smbpid,
7337                                                         e->brltype,
7338                                                         WINDOWS_LOCK,
7339                                                         e->offset,
7340                                                         e->count,
7341                                                         block_smbpid)) {
7342                                         TALLOC_FREE(br_lck);
7343                                         *async = true;
7344                                         return NT_STATUS_OK;
7345                                 }
7346                         }
7347
7348                         TALLOC_FREE(br_lck);
7349                 }
7350
7351                 if (!NT_STATUS_IS_OK(status)) {
7352                         break;
7353                 }
7354         }
7355
7356         /* If any of the above locks failed, then we must unlock
7357            all of the previous locks (X/Open spec). */
7358
7359         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7360
7361                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7362                         i = -1; /* we want to skip the for loop */
7363                 }
7364
7365                 /*
7366                  * Ensure we don't do a remove on the lock that just failed,
7367                  * as under POSIX rules, if we have a lock already there, we
7368                  * will delete it (and we shouldn't) .....
7369                  */
7370                 for(i--; i >= 0; i--) {
7371                         struct smbd_lock_element *e = &locks[i];
7372
7373                         do_unlock(smbd_messaging_context(),
7374                                 fsp,
7375                                 e->smbpid,
7376                                 e->count,
7377                                 e->offset,
7378                                 WINDOWS_LOCK);
7379                 }
7380                 return status;
7381         }
7382
7383         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7384                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7385
7386         return NT_STATUS_OK;
7387 }
7388
7389 /****************************************************************************
7390  Reply to a lockingX request.
7391 ****************************************************************************/
7392
7393 void reply_lockingX(struct smb_request *req)
7394 {
7395         connection_struct *conn = req->conn;
7396         files_struct *fsp;
7397         unsigned char locktype;
7398         unsigned char oplocklevel;
7399         uint16 num_ulocks;
7400         uint16 num_locks;
7401         int32 lock_timeout;
7402         int i;
7403         const uint8_t *data;
7404         bool large_file_format;
7405         bool err;
7406         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7407         struct smbd_lock_element *ulocks;
7408         struct smbd_lock_element *locks;
7409         bool async = false;
7410
7411         START_PROFILE(SMBlockingX);
7412
7413         if (req->wct < 8) {
7414                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7415                 END_PROFILE(SMBlockingX);
7416                 return;
7417         }
7418
7419         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7420         locktype = CVAL(req->vwv+3, 0);
7421         oplocklevel = CVAL(req->vwv+3, 1);
7422         num_ulocks = SVAL(req->vwv+6, 0);
7423         num_locks = SVAL(req->vwv+7, 0);
7424         lock_timeout = IVAL(req->vwv+4, 0);
7425         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7426
7427         if (!check_fsp(conn, req, fsp)) {
7428                 END_PROFILE(SMBlockingX);
7429                 return;
7430         }
7431
7432         data = req->buf;
7433
7434         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7435                 /* we don't support these - and CANCEL_LOCK makes w2k
7436                    and XP reboot so I don't really want to be
7437                    compatible! (tridge) */
7438                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7439                 END_PROFILE(SMBlockingX);
7440                 return;
7441         }
7442
7443         /* Check if this is an oplock break on a file
7444            we have granted an oplock on.
7445         */
7446         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7447                 /* Client can insist on breaking to none. */
7448                 bool break_to_none = (oplocklevel == 0);
7449                 bool result;
7450
7451                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7452                          "for fnum = %d\n", (unsigned int)oplocklevel,
7453                          fsp->fnum ));
7454
7455                 /*
7456                  * Make sure we have granted an exclusive or batch oplock on
7457                  * this file.
7458                  */
7459
7460                 if (fsp->oplock_type == 0) {
7461
7462                         /* The Samba4 nbench simulator doesn't understand
7463                            the difference between break to level2 and break
7464                            to none from level2 - it sends oplock break
7465                            replies in both cases. Don't keep logging an error
7466                            message here - just ignore it. JRA. */
7467
7468                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7469                                  "client for fnum = %d (oplock=%d) and no "
7470                                  "oplock granted on this file (%s).\n",
7471                                  fsp->fnum, fsp->oplock_type,
7472                                  fsp_str_dbg(fsp)));
7473
7474                         /* if this is a pure oplock break request then don't
7475                          * send a reply */
7476                         if (num_locks == 0 && num_ulocks == 0) {
7477                                 END_PROFILE(SMBlockingX);
7478                                 return;
7479                         } else {
7480                                 END_PROFILE(SMBlockingX);
7481                                 reply_doserror(req, ERRDOS, ERRlock);
7482                                 return;
7483                         }
7484                 }
7485
7486                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7487                     (break_to_none)) {
7488                         result = remove_oplock(fsp);
7489                 } else {
7490                         result = downgrade_oplock(fsp);
7491                 }
7492
7493                 if (!result) {
7494                         DEBUG(0, ("reply_lockingX: error in removing "
7495                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7496                         /* Hmmm. Is this panic justified? */
7497                         smb_panic("internal tdb error");
7498                 }
7499
7500                 reply_to_oplock_break_requests(fsp);
7501
7502                 /* if this is a pure oplock break request then don't send a
7503                  * reply */
7504                 if (num_locks == 0 && num_ulocks == 0) {
7505                         /* Sanity check - ensure a pure oplock break is not a
7506                            chained request. */
7507                         if(CVAL(req->vwv+0, 0) != 0xff)
7508                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7509                                          "break is a chained %d request !\n",
7510                                          (unsigned int)CVAL(req->vwv+0, 0)));
7511                         END_PROFILE(SMBlockingX);
7512                         return;
7513                 }
7514         }
7515
7516         if (req->buflen <
7517             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7518                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7519                 END_PROFILE(SMBlockingX);
7520                 return;
7521         }
7522
7523         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7524         if (ulocks == NULL) {
7525                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7526                 END_PROFILE(SMBlockingX);
7527                 return;
7528         }
7529
7530         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7531         if (locks == NULL) {
7532                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7533                 END_PROFILE(SMBlockingX);
7534                 return;
7535         }
7536
7537         /* Data now points at the beginning of the list
7538            of smb_unlkrng structs */
7539         for(i = 0; i < (int)num_ulocks; i++) {
7540                 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7541                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7542                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7543                 ulocks[i].brltype = UNLOCK_LOCK;
7544
7545                 /*
7546                  * There is no error code marked "stupid client bug".... :-).
7547                  */
7548                 if(err) {
7549                         END_PROFILE(SMBlockingX);
7550                         reply_doserror(req, ERRDOS, ERRnoaccess);
7551                         return;
7552                 }
7553         }
7554
7555         /* Now do any requested locks */
7556         data += ((large_file_format ? 20 : 10)*num_ulocks);
7557
7558         /* Data now points at the beginning of the list
7559            of smb_lkrng structs */
7560
7561         for(i = 0; i < (int)num_locks; i++) {
7562                 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7563                 locks[i].count = get_lock_count(data, i, large_file_format);
7564                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7565
7566                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7567                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7568                                 locks[i].brltype = PENDING_READ_LOCK;
7569                         } else {
7570                                 locks[i].brltype = READ_LOCK;
7571                         }
7572                 } else {
7573                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7574                                 locks[i].brltype = PENDING_WRITE_LOCK;
7575                         } else {
7576                                 locks[i].brltype = WRITE_LOCK;
7577                         }
7578                 }
7579
7580                 /*
7581                  * There is no error code marked "stupid client bug".... :-).
7582                  */
7583                 if(err) {
7584                         END_PROFILE(SMBlockingX);
7585                         reply_doserror(req, ERRDOS, ERRnoaccess);
7586                         return;
7587                 }
7588         }
7589
7590         status = smbd_do_locking(req, fsp,
7591                                  locktype, lock_timeout,
7592                                  num_ulocks, ulocks,
7593                                  num_locks, locks,
7594                                  &async);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 END_PROFILE(SMBlockingX);
7597                 reply_nterror(req, status);
7598                 return;
7599         }
7600         if (async) {
7601                 END_PROFILE(SMBlockingX);
7602                 return;
7603         }
7604
7605         reply_outbuf(req, 2, 0);
7606
7607         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7608                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7609
7610         END_PROFILE(SMBlockingX);
7611         chain_reply(req);
7612 }
7613
7614 #undef DBGC_CLASS
7615 #define DBGC_CLASS DBGC_ALL
7616
7617 /****************************************************************************
7618  Reply to a SMBreadbmpx (read block multiplex) request.
7619  Always reply with an error, if someone has a platform really needs this,
7620  please contact vl@samba.org
7621 ****************************************************************************/
7622
7623 void reply_readbmpx(struct smb_request *req)
7624 {
7625         START_PROFILE(SMBreadBmpx);
7626         reply_doserror(req, ERRSRV, ERRuseSTD);
7627         END_PROFILE(SMBreadBmpx);
7628         return;
7629 }
7630
7631 /****************************************************************************
7632  Reply to a SMBreadbs (read block multiplex secondary) request.
7633  Always reply with an error, if someone has a platform really needs this,
7634  please contact vl@samba.org
7635 ****************************************************************************/
7636
7637 void reply_readbs(struct smb_request *req)
7638 {
7639         START_PROFILE(SMBreadBs);
7640         reply_doserror(req, ERRSRV, ERRuseSTD);
7641         END_PROFILE(SMBreadBs);
7642         return;
7643 }
7644
7645 /****************************************************************************
7646  Reply to a SMBsetattrE.
7647 ****************************************************************************/
7648
7649 void reply_setattrE(struct smb_request *req)
7650 {
7651         connection_struct *conn = req->conn;
7652         struct smb_file_time ft;
7653         files_struct *fsp;
7654         NTSTATUS status;
7655
7656         START_PROFILE(SMBsetattrE);
7657         ZERO_STRUCT(ft);
7658
7659         if (req->wct < 7) {
7660                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7661                 goto out;
7662         }
7663
7664         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7665
7666         if(!fsp || (fsp->conn != conn)) {
7667                 reply_doserror(req, ERRDOS, ERRbadfid);
7668                 goto out;
7669         }
7670
7671         /*
7672          * Convert the DOS times into unix times.
7673          */
7674
7675         ft.atime = convert_time_t_to_timespec(
7676             srv_make_unix_date2(req->vwv+3));
7677         ft.mtime = convert_time_t_to_timespec(
7678             srv_make_unix_date2(req->vwv+5));
7679         ft.create_time = convert_time_t_to_timespec(
7680             srv_make_unix_date2(req->vwv+1));
7681
7682         reply_outbuf(req, 0, 0);
7683
7684         /* 
7685          * Patch from Ray Frush <frush@engr.colostate.edu>
7686          * Sometimes times are sent as zero - ignore them.
7687          */
7688
7689         /* Ensure we have a valid stat struct for the source. */
7690         status = vfs_stat_fsp(fsp);
7691         if (!NT_STATUS_IS_OK(status)) {
7692                 reply_nterror(req, status);
7693                 goto out;
7694         }
7695
7696         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7697         if (!NT_STATUS_IS_OK(status)) {
7698                 reply_doserror(req, ERRDOS, ERRnoaccess);
7699                 goto out;
7700         }
7701
7702         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7703                " createtime=%u\n",
7704                 fsp->fnum,
7705                 (unsigned int)ft.atime.tv_sec,
7706                 (unsigned int)ft.mtime.tv_sec,
7707                 (unsigned int)ft.create_time.tv_sec
7708                 ));
7709  out:
7710         END_PROFILE(SMBsetattrE);
7711         return;
7712 }
7713
7714
7715 /* Back from the dead for OS/2..... JRA. */
7716
7717 /****************************************************************************
7718  Reply to a SMBwritebmpx (write block multiplex primary) request.
7719  Always reply with an error, if someone has a platform really needs this,
7720  please contact vl@samba.org
7721 ****************************************************************************/
7722
7723 void reply_writebmpx(struct smb_request *req)
7724 {
7725         START_PROFILE(SMBwriteBmpx);
7726         reply_doserror(req, ERRSRV, ERRuseSTD);
7727         END_PROFILE(SMBwriteBmpx);
7728         return;
7729 }
7730
7731 /****************************************************************************
7732  Reply to a SMBwritebs (write block multiplex secondary) request.
7733  Always reply with an error, if someone has a platform really needs this,
7734  please contact vl@samba.org
7735 ****************************************************************************/
7736
7737 void reply_writebs(struct smb_request *req)
7738 {
7739         START_PROFILE(SMBwriteBs);
7740         reply_doserror(req, ERRSRV, ERRuseSTD);
7741         END_PROFILE(SMBwriteBs);
7742         return;
7743 }
7744
7745 /****************************************************************************
7746  Reply to a SMBgetattrE.
7747 ****************************************************************************/
7748
7749 void reply_getattrE(struct smb_request *req)
7750 {
7751         connection_struct *conn = req->conn;
7752         int mode;
7753         files_struct *fsp;
7754         struct timespec create_ts;
7755
7756         START_PROFILE(SMBgetattrE);
7757
7758         if (req->wct < 1) {
7759                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7760                 END_PROFILE(SMBgetattrE);
7761                 return;
7762         }
7763
7764         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7765
7766         if(!fsp || (fsp->conn != conn)) {
7767                 reply_doserror(req, ERRDOS, ERRbadfid);
7768                 END_PROFILE(SMBgetattrE);
7769                 return;
7770         }
7771
7772         /* Do an fstat on this file */
7773         if(fsp_stat(fsp)) {
7774                 reply_nterror(req, map_nt_error_from_unix(errno));
7775                 END_PROFILE(SMBgetattrE);
7776                 return;
7777         }
7778
7779         mode = dos_mode(conn, fsp->fsp_name);
7780
7781         /*
7782          * Convert the times into dos times. Set create
7783          * date to be last modify date as UNIX doesn't save
7784          * this.
7785          */
7786
7787         reply_outbuf(req, 11, 0);
7788
7789         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7790         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7791         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7792                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7793         /* Should we check pending modtime here ? JRA */
7794         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7795                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7796
7797         if (mode & aDIR) {
7798                 SIVAL(req->outbuf, smb_vwv6, 0);
7799                 SIVAL(req->outbuf, smb_vwv8, 0);
7800         } else {
7801                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7802                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7803                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7804         }
7805         SSVAL(req->outbuf,smb_vwv10, mode);
7806
7807         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7808
7809         END_PROFILE(SMBgetattrE);
7810         return;
7811 }