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