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