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