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