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