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