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