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