Remove "store create time" code, cause create time to be stored
[ira/wip.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "smbd/globals.h"
29
30 /****************************************************************************
31  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
32  path or anything including wildcards.
33  We're assuming here that '/' is not the second byte in any multibyte char
34  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
35  set.
36 ****************************************************************************/
37
38 /* Custom version for processing POSIX paths. */
39 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
40
41 static NTSTATUS check_path_syntax_internal(char *path,
42                                            bool posix_path,
43                                            bool *p_last_component_contains_wcard)
44 {
45         char *d = path;
46         const char *s = path;
47         NTSTATUS ret = NT_STATUS_OK;
48         bool start_of_name_component = True;
49         bool stream_started = false;
50
51         *p_last_component_contains_wcard = False;
52
53         while (*s) {
54                 if (stream_started) {
55                         switch (*s) {
56                         case '/':
57                         case '\\':
58                                 return NT_STATUS_OBJECT_NAME_INVALID;
59                         case ':':
60                                 if (s[1] == '\0') {
61                                         return NT_STATUS_OBJECT_NAME_INVALID;
62                                 }
63                                 if (strchr_m(&s[1], ':')) {
64                                         return NT_STATUS_OBJECT_NAME_INVALID;
65                                 }
66                                 break;
67                         }
68                 }
69
70                 if (!posix_path && !stream_started && *s == ':') {
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_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_doserror(req, ERRDOS, ERRnosuchshare);
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_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_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_doserror(req, ERRDOS, ERRbadfid);
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_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_nterror(req, NT_STATUS_DOS(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_doserror(req, ERRDOS,ERRnoaccess);
1793                 goto out;
1794         }
1795
1796         reply_outbuf(req, 7, 0);
1797         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1798         SSVAL(req->outbuf,smb_vwv1,fattr);
1799         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1800                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1801         } else {
1802                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1803         }
1804         SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1805         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1806
1807         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1808                 SCVAL(req->outbuf,smb_flg,
1809                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1810         }
1811
1812         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1813                 SCVAL(req->outbuf,smb_flg,
1814                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1815         }
1816  out:
1817         TALLOC_FREE(smb_fname);
1818         END_PROFILE(SMBopen);
1819         return;
1820 }
1821
1822 /****************************************************************************
1823  Reply to an open and X.
1824 ****************************************************************************/
1825
1826 void reply_open_and_X(struct smb_request *req)
1827 {
1828         connection_struct *conn = req->conn;
1829         struct smb_filename *smb_fname = NULL;
1830         char *fname = NULL;
1831         uint16 open_flags;
1832         int deny_mode;
1833         uint32 smb_attr;
1834         /* Breakout the oplock request bits so we can set the
1835                 reply bits separately. */
1836         int ex_oplock_request;
1837         int core_oplock_request;
1838         int oplock_request;
1839 #if 0
1840         int smb_sattr = SVAL(req->vwv+4, 0);
1841         uint32 smb_time = make_unix_date3(req->vwv+6);
1842 #endif
1843         int smb_ofun;
1844         uint32 fattr=0;
1845         int mtime=0;
1846         int smb_action = 0;
1847         files_struct *fsp;
1848         NTSTATUS status;
1849         uint64_t allocation_size;
1850         ssize_t retval = -1;
1851         uint32 access_mask;
1852         uint32 share_mode;
1853         uint32 create_disposition;
1854         uint32 create_options = 0;
1855         TALLOC_CTX *ctx = talloc_tos();
1856
1857         START_PROFILE(SMBopenX);
1858
1859         if (req->wct < 15) {
1860                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1861                 goto out;
1862         }
1863
1864         open_flags = SVAL(req->vwv+2, 0);
1865         deny_mode = SVAL(req->vwv+3, 0);
1866         smb_attr = SVAL(req->vwv+5, 0);
1867         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1868         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1869         oplock_request = ex_oplock_request | core_oplock_request;
1870         smb_ofun = SVAL(req->vwv+8, 0);
1871         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1872
1873         /* If it's an IPC, pass off the pipe handler. */
1874         if (IS_IPC(conn)) {
1875                 if (lp_nt_pipe_support()) {
1876                         reply_open_pipe_and_X(conn, req);
1877                 } else {
1878                         reply_doserror(req, ERRSRV, ERRaccess);
1879                 }
1880                 goto out;
1881         }
1882
1883         /* XXXX we need to handle passed times, sattr and flags */
1884         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1885                         STR_TERMINATE, &status);
1886         if (!NT_STATUS_IS_OK(status)) {
1887                 reply_nterror(req, status);
1888                 goto out;
1889         }
1890
1891         status = filename_convert(ctx,
1892                                 conn,
1893                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
1894                                 fname,
1895                                 0,
1896                                 NULL,
1897                                 &smb_fname);
1898         if (!NT_STATUS_IS_OK(status)) {
1899                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1900                         reply_botherror(req,
1901                                         NT_STATUS_PATH_NOT_COVERED,
1902                                         ERRSRV, ERRbadpath);
1903                         goto out;
1904                 }
1905                 reply_nterror(req, status);
1906                 goto out;
1907         }
1908
1909         if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1910                                          &access_mask, &share_mode,
1911                                          &create_disposition,
1912                                          &create_options)) {
1913                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1914                 goto out;
1915         }
1916
1917         status = SMB_VFS_CREATE_FILE(
1918                 conn,                                   /* conn */
1919                 req,                                    /* req */
1920                 0,                                      /* root_dir_fid */
1921                 smb_fname,                              /* fname */
1922                 access_mask,                            /* access_mask */
1923                 share_mode,                             /* share_access */
1924                 create_disposition,                     /* create_disposition*/
1925                 create_options,                         /* create_options */
1926                 smb_attr,                               /* file_attributes */
1927                 oplock_request,                         /* oplock_request */
1928                 0,                                      /* allocation_size */
1929                 NULL,                                   /* sd */
1930                 NULL,                                   /* ea_list */
1931                 &fsp,                                   /* result */
1932                 &smb_action);                           /* pinfo */
1933
1934         if (!NT_STATUS_IS_OK(status)) {
1935                 if (open_was_deferred(req->mid)) {
1936                         /* We have re-scheduled this call. */
1937                         goto out;
1938                 }
1939                 reply_openerror(req, status);
1940                 goto out;
1941         }
1942
1943         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1944            if the file is truncated or created. */
1945         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1946                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1947                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1948                         close_file(req, fsp, ERROR_CLOSE);
1949                         reply_nterror(req, NT_STATUS_DISK_FULL);
1950                         goto out;
1951                 }
1952                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1953                 if (retval < 0) {
1954                         close_file(req, fsp, ERROR_CLOSE);
1955                         reply_nterror(req, NT_STATUS_DISK_FULL);
1956                         goto out;
1957                 }
1958                 smb_fname->st.st_ex_size =
1959                     SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1960         }
1961
1962         fattr = dos_mode(conn, smb_fname);
1963         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1964         if (fattr & aDIR) {
1965                 close_file(req, fsp, ERROR_CLOSE);
1966                 reply_doserror(req, ERRDOS, ERRnoaccess);
1967                 goto out;
1968         }
1969
1970         /* If the caller set the extended oplock request bit
1971                 and we granted one (by whatever means) - set the
1972                 correct bit for extended oplock reply.
1973         */
1974
1975         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1976                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1977         }
1978
1979         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1980                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1981         }
1982
1983         /* If the caller set the core oplock request bit
1984                 and we granted one (by whatever means) - set the
1985                 correct bit for core oplock reply.
1986         */
1987
1988         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1989                 reply_outbuf(req, 19, 0);
1990         } else {
1991                 reply_outbuf(req, 15, 0);
1992         }
1993
1994         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1995                 SCVAL(req->outbuf, smb_flg,
1996                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1997         }
1998
1999         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2000                 SCVAL(req->outbuf, smb_flg,
2001                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2002         }
2003
2004         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2005         SSVAL(req->outbuf,smb_vwv3,fattr);
2006         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2007                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2008         } else {
2009                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2010         }
2011         SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2012         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2013         SSVAL(req->outbuf,smb_vwv11,smb_action);
2014
2015         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2016                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2017         }
2018
2019         chain_reply(req);
2020  out:
2021         TALLOC_FREE(smb_fname);
2022         END_PROFILE(SMBopenX);
2023         return;
2024 }
2025
2026 /****************************************************************************
2027  Reply to a SMBulogoffX.
2028 ****************************************************************************/
2029
2030 void reply_ulogoffX(struct smb_request *req)
2031 {
2032         struct smbd_server_connection *sconn = smbd_server_conn;
2033         user_struct *vuser;
2034
2035         START_PROFILE(SMBulogoffX);
2036
2037         vuser = get_valid_user_struct(sconn, req->vuid);
2038
2039         if(vuser == NULL) {
2040                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2041                          req->vuid));
2042         }
2043
2044         /* in user level security we are supposed to close any files
2045                 open by this user */
2046         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2047                 file_close_user(req->vuid);
2048         }
2049
2050         invalidate_vuid(sconn, req->vuid);
2051
2052         reply_outbuf(req, 2, 0);
2053
2054         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2055
2056         END_PROFILE(SMBulogoffX);
2057         req->vuid = UID_FIELD_INVALID;
2058         chain_reply(req);
2059 }
2060
2061 /****************************************************************************
2062  Reply to a mknew or a create.
2063 ****************************************************************************/
2064
2065 void reply_mknew(struct smb_request *req)
2066 {
2067         connection_struct *conn = req->conn;
2068         struct smb_filename *smb_fname = NULL;
2069         char *fname = NULL;
2070         uint32 fattr = 0;
2071         struct smb_file_time ft;
2072         files_struct *fsp;
2073         int oplock_request = 0;
2074         NTSTATUS status;
2075         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2076         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2077         uint32 create_disposition;
2078         uint32 create_options = 0;
2079         TALLOC_CTX *ctx = talloc_tos();
2080
2081         START_PROFILE(SMBcreate);
2082         ZERO_STRUCT(ft);
2083
2084         if (req->wct < 3) {
2085                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2086                 goto out;
2087         }
2088
2089         fattr = SVAL(req->vwv+0, 0);
2090         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2091
2092         /* mtime. */
2093         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2094
2095         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2096                             STR_TERMINATE, &status);
2097         if (!NT_STATUS_IS_OK(status)) {
2098                 reply_nterror(req, status);
2099                 goto out;
2100         }
2101
2102         status = filename_convert(ctx,
2103                                 conn,
2104                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2105                                 fname,
2106                                 0,
2107                                 NULL,
2108                                 &smb_fname);
2109         if (!NT_STATUS_IS_OK(status)) {
2110                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2111                         reply_botherror(req,
2112                                         NT_STATUS_PATH_NOT_COVERED,
2113                                         ERRSRV, ERRbadpath);
2114                         goto out;
2115                 }
2116                 reply_nterror(req, status);
2117                 goto out;
2118         }
2119
2120         if (fattr & aVOLID) {
2121                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2122                          "please report this\n",
2123                          smb_fname_str_dbg(smb_fname)));
2124         }
2125
2126         if(req->cmd == SMBmknew) {
2127                 /* We should fail if file exists. */
2128                 create_disposition = FILE_CREATE;
2129         } else {
2130                 /* Create if file doesn't exist, truncate if it does. */
2131                 create_disposition = FILE_OVERWRITE_IF;
2132         }
2133
2134         status = SMB_VFS_CREATE_FILE(
2135                 conn,                                   /* conn */
2136                 req,                                    /* req */
2137                 0,                                      /* root_dir_fid */
2138                 smb_fname,                              /* fname */
2139                 access_mask,                            /* access_mask */
2140                 share_mode,                             /* share_access */
2141                 create_disposition,                     /* create_disposition*/
2142                 create_options,                         /* create_options */
2143                 fattr,                                  /* file_attributes */
2144                 oplock_request,                         /* oplock_request */
2145                 0,                                      /* allocation_size */
2146                 NULL,                                   /* sd */
2147                 NULL,                                   /* ea_list */
2148                 &fsp,                                   /* result */
2149                 NULL);                                  /* pinfo */
2150
2151         if (!NT_STATUS_IS_OK(status)) {
2152                 if (open_was_deferred(req->mid)) {
2153                         /* We have re-scheduled this call. */
2154                         goto out;
2155                 }
2156                 reply_openerror(req, status);
2157                 goto out;
2158         }
2159
2160         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2161         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2162         if (!NT_STATUS_IS_OK(status)) {
2163                 END_PROFILE(SMBcreate);
2164                 goto out;
2165         }
2166
2167         reply_outbuf(req, 1, 0);
2168         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2169
2170         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171                 SCVAL(req->outbuf,smb_flg,
2172                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2173         }
2174
2175         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176                 SCVAL(req->outbuf,smb_flg,
2177                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2178         }
2179
2180         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2181         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2182                   smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2183                   (unsigned int)fattr));
2184
2185  out:
2186         TALLOC_FREE(smb_fname);
2187         END_PROFILE(SMBcreate);
2188         return;
2189 }
2190
2191 /****************************************************************************
2192  Reply to a create temporary file.
2193 ****************************************************************************/
2194
2195 void reply_ctemp(struct smb_request *req)
2196 {
2197         connection_struct *conn = req->conn;
2198         struct smb_filename *smb_fname = NULL;
2199         char *fname = NULL;
2200         uint32 fattr;
2201         files_struct *fsp;
2202         int oplock_request;
2203         int tmpfd;
2204         char *s;
2205         NTSTATUS status;
2206         TALLOC_CTX *ctx = talloc_tos();
2207
2208         START_PROFILE(SMBctemp);
2209
2210         if (req->wct < 3) {
2211                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2212                 goto out;
2213         }
2214
2215         fattr = SVAL(req->vwv+0, 0);
2216         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2217
2218         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2219                             STR_TERMINATE, &status);
2220         if (!NT_STATUS_IS_OK(status)) {
2221                 reply_nterror(req, status);
2222                 goto out;
2223         }
2224         if (*fname) {
2225                 fname = talloc_asprintf(ctx,
2226                                 "%s/TMXXXXXX",
2227                                 fname);
2228         } else {
2229                 fname = talloc_strdup(ctx, "TMXXXXXX");
2230         }
2231
2232         if (!fname) {
2233                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2234                 goto out;
2235         }
2236
2237         status = filename_convert(ctx, conn,
2238                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
2239                                 fname,
2240                                 0,
2241                                 NULL,
2242                                 &smb_fname);
2243         if (!NT_STATUS_IS_OK(status)) {
2244                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2245                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2246                                         ERRSRV, ERRbadpath);
2247                         goto out;
2248                 }
2249                 reply_nterror(req, status);
2250                 goto out;
2251         }
2252
2253         tmpfd = mkstemp(smb_fname->base_name);
2254         if (tmpfd == -1) {
2255                 reply_nterror(req, map_nt_error_from_unix(errno));
2256                 goto out;
2257         }
2258
2259         SMB_VFS_STAT(conn, smb_fname);
2260
2261         /* We should fail if file does not exist. */
2262         status = SMB_VFS_CREATE_FILE(
2263                 conn,                                   /* conn */
2264                 req,                                    /* req */
2265                 0,                                      /* root_dir_fid */
2266                 smb_fname,                              /* fname */
2267                 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2268                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2269                 FILE_OPEN,                              /* create_disposition*/
2270                 0,                                      /* create_options */
2271                 fattr,                                  /* file_attributes */
2272                 oplock_request,                         /* oplock_request */
2273                 0,                                      /* allocation_size */
2274                 NULL,                                   /* sd */
2275                 NULL,                                   /* ea_list */
2276                 &fsp,                                   /* result */
2277                 NULL);                                  /* pinfo */
2278
2279         /* close fd from mkstemp() */
2280         close(tmpfd);
2281
2282         if (!NT_STATUS_IS_OK(status)) {
2283                 if (open_was_deferred(req->mid)) {
2284                         /* We have re-scheduled this call. */
2285                         goto out;
2286                 }
2287                 reply_openerror(req, status);
2288                 goto out;
2289         }
2290
2291         reply_outbuf(req, 1, 0);
2292         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2293
2294         /* the returned filename is relative to the directory */
2295         s = strrchr_m(fsp->fsp_name->base_name, '/');
2296         if (!s) {
2297                 s = fsp->fsp_name->base_name;
2298         } else {
2299                 s++;
2300         }
2301
2302 #if 0
2303         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2304            thing in the byte section. JRA */
2305         SSVALS(p, 0, -1); /* what is this? not in spec */
2306 #endif
2307         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2308             == -1) {
2309                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2310                 goto out;
2311         }
2312
2313         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2314                 SCVAL(req->outbuf, smb_flg,
2315                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2316         }
2317
2318         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2319                 SCVAL(req->outbuf, smb_flg,
2320                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2321         }
2322
2323         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2324         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2325                     fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2326  out:
2327         TALLOC_FREE(smb_fname);
2328         END_PROFILE(SMBctemp);
2329         return;
2330 }
2331
2332 /*******************************************************************
2333  Check if a user is allowed to rename a file.
2334 ********************************************************************/
2335
2336 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2337                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2338 {
2339         uint32 fmode;
2340
2341         if (!CAN_WRITE(conn)) {
2342                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2343         }
2344
2345         fmode = dos_mode(conn, fsp->fsp_name);
2346         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2347                 return NT_STATUS_NO_SUCH_FILE;
2348         }
2349
2350         if (S_ISDIR(pst->st_ex_mode)) {
2351                 if (fsp->posix_open) {
2352                         return NT_STATUS_OK;
2353                 }
2354
2355                 /* If no pathnames are open below this
2356                    directory, allow the rename. */
2357
2358                 if (file_find_subpath(fsp)) {
2359                         return NT_STATUS_ACCESS_DENIED;
2360                 }
2361                 return NT_STATUS_OK;
2362         }
2363
2364         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2365                 return NT_STATUS_OK;
2366         }
2367
2368         return NT_STATUS_ACCESS_DENIED;
2369 }
2370
2371 /*******************************************************************
2372  * unlink a file with all relevant access checks
2373  *******************************************************************/
2374
2375 static NTSTATUS do_unlink(connection_struct *conn,
2376                         struct smb_request *req,
2377                         struct smb_filename *smb_fname,
2378                         uint32 dirtype)
2379 {
2380         uint32 fattr;
2381         files_struct *fsp;
2382         uint32 dirtype_orig = dirtype;
2383         NTSTATUS status;
2384         int ret;
2385         bool posix_paths = lp_posix_pathnames();
2386
2387         DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2388                   smb_fname_str_dbg(smb_fname),
2389                   dirtype));
2390
2391         if (!CAN_WRITE(conn)) {
2392                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2393         }
2394
2395         if (posix_paths) {
2396                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2397         } else {
2398                 ret = SMB_VFS_LSTAT(conn, smb_fname);
2399         }
2400         if (ret != 0) {
2401                 return map_nt_error_from_unix(errno);
2402         }
2403
2404         fattr = dos_mode(conn, smb_fname);
2405
2406         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2407                 dirtype = aDIR|aARCH|aRONLY;
2408         }
2409
2410         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2411         if (!dirtype) {
2412                 return NT_STATUS_NO_SUCH_FILE;
2413         }
2414
2415         if (!dir_check_ftype(conn, fattr, dirtype)) {
2416                 if (fattr & aDIR) {
2417                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2418                 }
2419                 return NT_STATUS_NO_SUCH_FILE;
2420         }
2421
2422         if (dirtype_orig & 0x8000) {
2423                 /* These will never be set for POSIX. */
2424                 return NT_STATUS_NO_SUCH_FILE;
2425         }
2426
2427 #if 0
2428         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2429                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2430         }
2431
2432         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2433                 return NT_STATUS_NO_SUCH_FILE;
2434         }
2435
2436         if (dirtype & 0xFF00) {
2437                 /* These will never be set for POSIX. */
2438                 return NT_STATUS_NO_SUCH_FILE;
2439         }
2440
2441         dirtype &= 0xFF;
2442         if (!dirtype) {
2443                 return NT_STATUS_NO_SUCH_FILE;
2444         }
2445
2446         /* Can't delete a directory. */
2447         if (fattr & aDIR) {
2448                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2449         }
2450 #endif
2451
2452 #if 0 /* JRATEST */
2453         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2454                 return NT_STATUS_OBJECT_NAME_INVALID;
2455 #endif /* JRATEST */
2456
2457         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2458
2459           On a Windows share, a file with read-only dosmode can be opened with
2460           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2461           fails with NT_STATUS_CANNOT_DELETE error.
2462
2463           This semantic causes a problem that a user can not
2464           rename a file with read-only dosmode on a Samba share
2465           from a Windows command prompt (i.e. cmd.exe, but can rename
2466           from Windows Explorer).
2467         */
2468
2469         if (!lp_delete_readonly(SNUM(conn))) {
2470                 if (fattr & aRONLY) {
2471                         return NT_STATUS_CANNOT_DELETE;
2472                 }
2473         }
2474
2475         /* On open checks the open itself will check the share mode, so
2476            don't do it here as we'll get it wrong. */
2477
2478         status = SMB_VFS_CREATE_FILE
2479                 (conn,                  /* conn */
2480                  req,                   /* req */
2481                  0,                     /* root_dir_fid */
2482                  smb_fname,             /* fname */
2483                  DELETE_ACCESS,         /* access_mask */
2484                  FILE_SHARE_NONE,       /* share_access */
2485                  FILE_OPEN,             /* create_disposition*/
2486                  FILE_NON_DIRECTORY_FILE, /* create_options */
2487                                         /* file_attributes */
2488                  posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2489                                 FILE_ATTRIBUTE_NORMAL,
2490                  0,                     /* oplock_request */
2491                  0,                     /* allocation_size */
2492                  NULL,                  /* sd */
2493                  NULL,                  /* ea_list */
2494                  &fsp,                  /* result */
2495                  NULL);                 /* pinfo */
2496
2497         if (!NT_STATUS_IS_OK(status)) {
2498                 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2499                            nt_errstr(status)));
2500                 return status;
2501         }
2502
2503         /* The set is across all open files on this dev/inode pair. */
2504         if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2505                 close_file(req, fsp, NORMAL_CLOSE);
2506                 return NT_STATUS_ACCESS_DENIED;
2507         }
2508
2509         return close_file(req, fsp, NORMAL_CLOSE);
2510 }
2511
2512 /****************************************************************************
2513  The guts of the unlink command, split out so it may be called by the NT SMB
2514  code.
2515 ****************************************************************************/
2516
2517 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2518                           uint32 dirtype, struct smb_filename *smb_fname,
2519                           bool has_wild)
2520 {
2521         char *fname_dir = NULL;
2522         char *fname_mask = NULL;
2523         int count=0;
2524         NTSTATUS status = NT_STATUS_OK;
2525         TALLOC_CTX *ctx = talloc_tos();
2526
2527         /* Split up the directory from the filename/mask. */
2528         status = split_fname_dir_mask(ctx, smb_fname->base_name,
2529                                       &fname_dir, &fname_mask);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 goto out;
2532         }
2533
2534         /*
2535          * We should only check the mangled cache
2536          * here if unix_convert failed. This means
2537          * that the path in 'mask' doesn't exist
2538          * on the file system and so we need to look
2539          * for a possible mangle. This patch from
2540          * Tine Smukavec <valentin.smukavec@hermes.si>.
2541          */
2542
2543         if (!VALID_STAT(smb_fname->st) &&
2544             mangle_is_mangled(fname_mask, conn->params)) {
2545                 char *new_mask = NULL;
2546                 mangle_lookup_name_from_8_3(ctx, fname_mask,
2547                                             &new_mask, conn->params);
2548                 if (new_mask) {
2549                         TALLOC_FREE(fname_mask);
2550                         fname_mask = new_mask;
2551                 }
2552         }
2553
2554         if (!has_wild) {
2555
2556                 /*
2557                  * Only one file needs to be unlinked. Append the mask back
2558                  * onto the directory.
2559                  */
2560                 TALLOC_FREE(smb_fname->base_name);
2561                 smb_fname->base_name = talloc_asprintf(smb_fname,
2562                                                        "%s/%s",
2563                                                        fname_dir,
2564                                                        fname_mask);
2565                 if (!smb_fname->base_name) {
2566                         status = NT_STATUS_NO_MEMORY;
2567                         goto out;
2568                 }
2569                 if (dirtype == 0) {
2570                         dirtype = FILE_ATTRIBUTE_NORMAL;
2571                 }
2572
2573                 status = check_name(conn, smb_fname->base_name);
2574                 if (!NT_STATUS_IS_OK(status)) {
2575                         goto out;
2576                 }
2577
2578                 status = do_unlink(conn, req, smb_fname, dirtype);
2579                 if (!NT_STATUS_IS_OK(status)) {
2580                         goto out;
2581                 }
2582
2583                 count++;
2584         } else {
2585                 struct smb_Dir *dir_hnd = NULL;
2586                 long offset = 0;
2587                 char *dname = NULL;
2588
2589                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2590                         status = NT_STATUS_OBJECT_NAME_INVALID;
2591                         goto out;
2592                 }
2593
2594                 if (strequal(fname_mask,"????????.???")) {
2595                         TALLOC_FREE(fname_mask);
2596                         fname_mask = talloc_strdup(ctx, "*");
2597                         if (!fname_mask) {
2598                                 status = NT_STATUS_NO_MEMORY;
2599                                 goto out;
2600                         }
2601                 }
2602
2603                 status = check_name(conn, fname_dir);
2604                 if (!NT_STATUS_IS_OK(status)) {
2605                         goto out;
2606                 }
2607
2608                 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2609                                   dirtype);
2610                 if (dir_hnd == NULL) {
2611                         status = map_nt_error_from_unix(errno);
2612                         goto out;
2613                 }
2614
2615                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2616                    the pattern matches against the long name, otherwise the short name 
2617                    We don't implement this yet XXXX
2618                 */
2619
2620                 status = NT_STATUS_NO_SUCH_FILE;
2621
2622                 while ((dname = ReadDirName(dir_hnd, &offset,
2623                                             &smb_fname->st))) {
2624                         TALLOC_CTX *frame = talloc_stackframe();
2625
2626                         if (!is_visible_file(conn, fname_dir, dname,
2627                                              &smb_fname->st, true)) {
2628                                 TALLOC_FREE(frame);
2629                                 TALLOC_FREE(dname);
2630                                 continue;
2631                         }
2632
2633                         /* Quick check for "." and ".." */
2634                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2635                                 TALLOC_FREE(frame);
2636                                 TALLOC_FREE(dname);
2637                                 continue;
2638                         }
2639
2640                         if(!mask_match(dname, fname_mask,
2641                                        conn->case_sensitive)) {
2642                                 TALLOC_FREE(frame);
2643                                 TALLOC_FREE(dname);
2644                                 continue;
2645                         }
2646
2647                         TALLOC_FREE(smb_fname->base_name);
2648                         smb_fname->base_name =
2649                             talloc_asprintf(smb_fname, "%s/%s",
2650                                             fname_dir, dname);
2651
2652                         if (!smb_fname->base_name) {
2653                                 TALLOC_FREE(dir_hnd);
2654                                 status = NT_STATUS_NO_MEMORY;
2655                                 TALLOC_FREE(frame);
2656                                 TALLOC_FREE(dname);
2657                                 goto out;
2658                         }
2659
2660                         status = check_name(conn, smb_fname->base_name);
2661                         if (!NT_STATUS_IS_OK(status)) {
2662                                 TALLOC_FREE(dir_hnd);
2663                                 TALLOC_FREE(frame);
2664                                 TALLOC_FREE(dname);
2665                                 goto out;
2666                         }
2667
2668                         status = do_unlink(conn, req, smb_fname, dirtype);
2669                         if (!NT_STATUS_IS_OK(status)) {
2670                                 TALLOC_FREE(frame);
2671                                 TALLOC_FREE(dname);
2672                                 continue;
2673                         }
2674
2675                         count++;
2676                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2677                                  smb_fname->base_name));
2678
2679                         TALLOC_FREE(frame);
2680                         TALLOC_FREE(dname);
2681                 }
2682                 TALLOC_FREE(dir_hnd);
2683         }
2684
2685         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2686                 status = map_nt_error_from_unix(errno);
2687         }
2688
2689  out:
2690         TALLOC_FREE(fname_dir);
2691         TALLOC_FREE(fname_mask);
2692         return status;
2693 }
2694
2695 /****************************************************************************
2696  Reply to a unlink
2697 ****************************************************************************/
2698
2699 void reply_unlink(struct smb_request *req)
2700 {
2701         connection_struct *conn = req->conn;
2702         char *name = NULL;
2703         struct smb_filename *smb_fname = NULL;
2704         uint32 dirtype;
2705         NTSTATUS status;
2706         bool path_contains_wcard = False;
2707         TALLOC_CTX *ctx = talloc_tos();
2708
2709         START_PROFILE(SMBunlink);
2710
2711         if (req->wct < 1) {
2712                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2713                 goto out;
2714         }
2715
2716         dirtype = SVAL(req->vwv+0, 0);
2717
2718         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2719                                   STR_TERMINATE, &status,
2720                                   &path_contains_wcard);
2721         if (!NT_STATUS_IS_OK(status)) {
2722                 reply_nterror(req, status);
2723                 goto out;
2724         }
2725
2726         status = filename_convert(ctx, conn,
2727                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
2728                                   name,
2729                                   UCF_COND_ALLOW_WCARD_LCOMP,
2730                                   &path_contains_wcard,
2731                                   &smb_fname);
2732         if (!NT_STATUS_IS_OK(status)) {
2733                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2734                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2735                                         ERRSRV, ERRbadpath);
2736                         goto out;
2737                 }
2738                 reply_nterror(req, status);
2739                 goto out;
2740         }
2741
2742         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2743
2744         status = unlink_internals(conn, req, dirtype, smb_fname,
2745                                   path_contains_wcard);
2746         if (!NT_STATUS_IS_OK(status)) {
2747                 if (open_was_deferred(req->mid)) {
2748                         /* We have re-scheduled this call. */
2749                         goto out;
2750                 }
2751                 reply_nterror(req, status);
2752                 goto out;
2753         }
2754
2755         reply_outbuf(req, 0, 0);
2756  out:
2757         TALLOC_FREE(smb_fname);
2758         END_PROFILE(SMBunlink);
2759         return;
2760 }
2761
2762 /****************************************************************************
2763  Fail for readbraw.
2764 ****************************************************************************/
2765
2766 static void fail_readraw(void)
2767 {
2768         const char *errstr = talloc_asprintf(talloc_tos(),
2769                         "FAIL ! reply_readbraw: socket write fail (%s)",
2770                         strerror(errno));
2771         if (!errstr) {
2772                 errstr = "";
2773         }
2774         exit_server_cleanly(errstr);
2775 }
2776
2777 /****************************************************************************
2778  Fake (read/write) sendfile. Returns -1 on read or write fail.
2779 ****************************************************************************/
2780
2781 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2782                              size_t nread)
2783 {
2784         size_t bufsize;
2785         size_t tosend = nread;
2786         char *buf;
2787
2788         if (nread == 0) {
2789                 return 0;
2790         }
2791
2792         bufsize = MIN(nread, 65536);
2793
2794         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2795                 return -1;
2796         }
2797
2798         while (tosend > 0) {
2799                 ssize_t ret;
2800                 size_t cur_read;
2801
2802                 if (tosend > bufsize) {
2803                         cur_read = bufsize;
2804                 } else {
2805                         cur_read = tosend;
2806                 }
2807                 ret = read_file(fsp,buf,startpos,cur_read);
2808                 if (ret == -1) {
2809                         SAFE_FREE(buf);
2810                         return -1;
2811                 }
2812
2813                 /* If we had a short read, fill with zeros. */
2814                 if (ret < cur_read) {
2815                         memset(buf + ret, '\0', cur_read - ret);
2816                 }
2817
2818                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2819                         SAFE_FREE(buf);
2820                         return -1;
2821                 }
2822                 tosend -= cur_read;
2823                 startpos += cur_read;
2824         }
2825
2826         SAFE_FREE(buf);
2827         return (ssize_t)nread;
2828 }
2829
2830 #if defined(WITH_SENDFILE)
2831 /****************************************************************************
2832  Deal with the case of sendfile reading less bytes from the file than
2833  requested. Fill with zeros (all we can do).
2834 ****************************************************************************/
2835
2836 static void sendfile_short_send(files_struct *fsp,
2837                                 ssize_t nread,
2838                                 size_t headersize,
2839                                 size_t smb_maxcnt)
2840 {
2841 #define SHORT_SEND_BUFSIZE 1024
2842         if (nread < headersize) {
2843                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2844                         "header for file %s (%s). Terminating\n",
2845                         fsp_str_dbg(fsp), strerror(errno)));
2846                 exit_server_cleanly("sendfile_short_send failed");
2847         }
2848
2849         nread -= headersize;
2850
2851         if (nread < smb_maxcnt) {
2852                 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2853                 if (!buf) {
2854                         exit_server_cleanly("sendfile_short_send: "
2855                                 "malloc failed");
2856                 }
2857
2858                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2859                         "with zeros !\n", fsp_str_dbg(fsp)));
2860
2861                 while (nread < smb_maxcnt) {
2862                         /*
2863                          * We asked for the real file size and told sendfile
2864                          * to not go beyond the end of the file. But it can
2865                          * happen that in between our fstat call and the
2866                          * sendfile call the file was truncated. This is very
2867                          * bad because we have already announced the larger
2868                          * number of bytes to the client.
2869                          *
2870                          * The best we can do now is to send 0-bytes, just as
2871                          * a read from a hole in a sparse file would do.
2872                          *
2873                          * This should happen rarely enough that I don't care
2874                          * about efficiency here :-)
2875                          */
2876                         size_t to_write;
2877
2878                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2879                         if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2880                                 exit_server_cleanly("sendfile_short_send: "
2881                                         "write_data failed");
2882                         }
2883                         nread += to_write;
2884                 }
2885                 SAFE_FREE(buf);
2886         }
2887 }
2888 #endif /* defined WITH_SENDFILE */
2889
2890 /****************************************************************************
2891  Return a readbraw error (4 bytes of zero).
2892 ****************************************************************************/
2893
2894 static void reply_readbraw_error(void)
2895 {
2896         char header[4];
2897         SIVAL(header,0,0);
2898         if (write_data(smbd_server_fd(),header,4) != 4) {
2899                 fail_readraw();
2900         }
2901 }
2902
2903 /****************************************************************************
2904  Use sendfile in readbraw.
2905 ****************************************************************************/
2906
2907 static void send_file_readbraw(connection_struct *conn,
2908                                struct smb_request *req,
2909                                files_struct *fsp,
2910                                SMB_OFF_T startpos,
2911                                size_t nread,
2912                                ssize_t mincount)
2913 {
2914         char *outbuf = NULL;
2915         ssize_t ret=0;
2916
2917 #if defined(WITH_SENDFILE)
2918         /*
2919          * We can only use sendfile on a non-chained packet 
2920          * but we can use on a non-oplocked file. tridge proved this
2921          * on a train in Germany :-). JRA.
2922          * reply_readbraw has already checked the length.
2923          */
2924
2925         if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2926             (fsp->wcp == NULL) &&
2927             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2928                 ssize_t sendfile_read = -1;
2929                 char header[4];
2930                 DATA_BLOB header_blob;
2931
2932                 _smb_setlen(header,nread);
2933                 header_blob = data_blob_const(header, 4);
2934
2935                 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2936                                 &header_blob, startpos, nread)) == -1) {
2937                         /* Returning ENOSYS means no data at all was sent.
2938                          * Do this as a normal read. */
2939                         if (errno == ENOSYS) {
2940                                 goto normal_readbraw;
2941                         }
2942
2943                         /*
2944                          * Special hack for broken Linux with no working sendfile. If we
2945                          * return EINTR we sent the header but not the rest of the data.
2946                          * Fake this up by doing read/write calls.
2947                          */
2948                         if (errno == EINTR) {
2949                                 /* Ensure we don't do this again. */
2950                                 set_use_sendfile(SNUM(conn), False);
2951                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2952
2953                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2954                                         DEBUG(0,("send_file_readbraw: "
2955                                                  "fake_sendfile failed for "
2956                                                  "file %s (%s).\n",
2957                                                  fsp_str_dbg(fsp),
2958                                                  strerror(errno)));
2959                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2960                                 }
2961                                 return;
2962                         }
2963
2964                         DEBUG(0,("send_file_readbraw: sendfile failed for "
2965                                  "file %s (%s). Terminating\n",
2966                                  fsp_str_dbg(fsp), strerror(errno)));
2967                         exit_server_cleanly("send_file_readbraw sendfile failed");
2968                 } else if (sendfile_read == 0) {
2969                         /*
2970                          * Some sendfile implementations return 0 to indicate
2971                          * that there was a short read, but nothing was
2972                          * actually written to the socket.  In this case,
2973                          * fallback to the normal read path so the header gets
2974                          * the correct byte count.
2975                          */
2976                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2977                                   "bytes falling back to the normal read: "
2978                                   "%s\n", fsp_str_dbg(fsp)));
2979                         goto normal_readbraw;
2980                 }
2981
2982                 /* Deal with possible short send. */
2983                 if (sendfile_read != 4+nread) {
2984                         sendfile_short_send(fsp, sendfile_read, 4, nread);
2985                 }
2986                 return;
2987         }
2988
2989 normal_readbraw:
2990 #endif
2991
2992         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2993         if (!outbuf) {
2994                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2995                         (unsigned)(nread+4)));
2996                 reply_readbraw_error();
2997                 return;
2998         }
2999
3000         if (nread > 0) {
3001                 ret = read_file(fsp,outbuf+4,startpos,nread);
3002 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3003                 if (ret < mincount)
3004                         ret = 0;
3005 #else
3006                 if (ret < nread)
3007                         ret = 0;
3008 #endif
3009         }
3010
3011         _smb_setlen(outbuf,ret);
3012         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3013                 fail_readraw();
3014
3015         TALLOC_FREE(outbuf);
3016 }
3017
3018 /****************************************************************************
3019  Reply to a readbraw (core+ protocol).
3020 ****************************************************************************/
3021
3022 void reply_readbraw(struct smb_request *req)
3023 {
3024         connection_struct *conn = req->conn;
3025         ssize_t maxcount,mincount;
3026         size_t nread = 0;
3027         SMB_OFF_T startpos;
3028         files_struct *fsp;
3029         struct lock_struct lock;
3030         SMB_STRUCT_STAT st;
3031         SMB_OFF_T size = 0;
3032
3033         START_PROFILE(SMBreadbraw);
3034
3035         if (srv_is_signing_active(smbd_server_conn) ||
3036             is_encrypted_packet(req->inbuf)) {
3037                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3038                         "raw reads/writes are disallowed.");
3039         }
3040
3041         if (req->wct < 8) {
3042                 reply_readbraw_error();
3043                 END_PROFILE(SMBreadbraw);
3044                 return;
3045         }
3046
3047         /*
3048          * Special check if an oplock break has been issued
3049          * and the readraw request croses on the wire, we must
3050          * return a zero length response here.
3051          */
3052
3053         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3054
3055         /*
3056          * We have to do a check_fsp by hand here, as
3057          * we must always return 4 zero bytes on error,
3058          * not a NTSTATUS.
3059          */
3060
3061         if (!fsp || !conn || conn != fsp->conn ||
3062                         req->vuid != fsp->vuid ||
3063                         fsp->is_directory || fsp->fh->fd == -1) {
3064                 /*
3065                  * fsp could be NULL here so use the value from the packet. JRA.
3066                  */
3067                 DEBUG(3,("reply_readbraw: fnum %d not valid "
3068                         "- cache prime?\n",
3069                         (int)SVAL(req->vwv+0, 0)));
3070                 reply_readbraw_error();
3071                 END_PROFILE(SMBreadbraw);
3072                 return;
3073         }
3074
3075         /* Do a "by hand" version of CHECK_READ. */
3076         if (!(fsp->can_read ||
3077                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3078                                 (fsp->access_mask & FILE_EXECUTE)))) {
3079                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3080                                 (int)SVAL(req->vwv+0, 0)));
3081                 reply_readbraw_error();
3082                 END_PROFILE(SMBreadbraw);
3083                 return;
3084         }
3085
3086         flush_write_cache(fsp, READRAW_FLUSH);
3087
3088         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3089         if(req->wct == 10) {
3090                 /*
3091                  * This is a large offset (64 bit) read.
3092                  */
3093 #ifdef LARGE_SMB_OFF_T
3094
3095                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3096
3097 #else /* !LARGE_SMB_OFF_T */
3098
3099                 /*
3100                  * Ensure we haven't been sent a >32 bit offset.
3101                  */
3102
3103                 if(IVAL(req->vwv+8, 0) != 0) {
3104                         DEBUG(0,("reply_readbraw: large offset "
3105                                 "(%x << 32) used and we don't support "
3106                                 "64 bit offsets.\n",
3107                         (unsigned int)IVAL(req->vwv+8, 0) ));
3108                         reply_readbraw_error();
3109                         END_PROFILE(SMBreadbraw);
3110                         return;
3111                 }
3112
3113 #endif /* LARGE_SMB_OFF_T */
3114
3115                 if(startpos < 0) {
3116                         DEBUG(0,("reply_readbraw: negative 64 bit "
3117                                 "readraw offset (%.0f) !\n",
3118                                 (double)startpos ));
3119                         reply_readbraw_error();
3120                         END_PROFILE(SMBreadbraw);
3121                         return;
3122                 }      
3123         }
3124
3125         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3126         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3127
3128         /* ensure we don't overrun the packet size */
3129         maxcount = MIN(65535,maxcount);
3130
3131         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3132             (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3133             &lock);
3134
3135         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3136                 reply_readbraw_error();
3137                 END_PROFILE(SMBreadbraw);
3138                 return;
3139         }
3140
3141         if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3142                 size = st.st_ex_size;
3143         }
3144
3145         if (startpos >= size) {
3146                 nread = 0;
3147         } else {
3148                 nread = MIN(maxcount,(size - startpos));
3149         }
3150
3151 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3152         if (nread < mincount)
3153                 nread = 0;
3154 #endif
3155
3156         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3157                 "min=%lu nread=%lu\n",
3158                 fsp->fnum, (double)startpos,
3159                 (unsigned long)maxcount,
3160                 (unsigned long)mincount,
3161                 (unsigned long)nread ) );
3162
3163         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3164
3165         DEBUG(5,("reply_readbraw finished\n"));
3166
3167         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3168
3169         END_PROFILE(SMBreadbraw);
3170         return;
3171 }
3172
3173 #undef DBGC_CLASS
3174 #define DBGC_CLASS DBGC_LOCKING
3175
3176 /****************************************************************************
3177  Reply to a lockread (core+ protocol).
3178 ****************************************************************************/
3179
3180 void reply_lockread(struct smb_request *req)
3181 {
3182         connection_struct *conn = req->conn;
3183         ssize_t nread = -1;
3184         char *data;
3185         SMB_OFF_T startpos;
3186         size_t numtoread;
3187         NTSTATUS status;
3188         files_struct *fsp;
3189         struct byte_range_lock *br_lck = NULL;
3190         char *p = NULL;
3191         struct smbd_server_connection *sconn = smbd_server_conn;
3192
3193         START_PROFILE(SMBlockread);
3194
3195         if (req->wct < 5) {
3196                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3197                 END_PROFILE(SMBlockread);
3198                 return;
3199         }
3200
3201         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3202
3203         if (!check_fsp(conn, req, fsp)) {
3204                 END_PROFILE(SMBlockread);
3205                 return;
3206         }
3207
3208         if (!CHECK_READ(fsp,req)) {
3209                 reply_doserror(req, ERRDOS, ERRbadaccess);
3210                 END_PROFILE(SMBlockread);
3211                 return;
3212         }
3213
3214         numtoread = SVAL(req->vwv+1, 0);
3215         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3216
3217         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3218
3219         reply_outbuf(req, 5, numtoread + 3);
3220
3221         data = smb_buf(req->outbuf) + 3;
3222
3223         /*
3224          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3225          * protocol request that predates the read/write lock concept. 
3226          * Thus instead of asking for a read lock here we need to ask
3227          * for a write lock. JRA.
3228          * Note that the requested lock size is unaffected by max_recv.
3229          */
3230
3231         br_lck = do_lock(smbd_messaging_context(),
3232                         fsp,
3233                         req->smbpid,
3234                         (uint64_t)numtoread,
3235                         (uint64_t)startpos,
3236                         WRITE_LOCK,
3237                         WINDOWS_LOCK,
3238                         False, /* Non-blocking lock. */
3239                         &status,
3240                         NULL,
3241                         NULL);
3242         TALLOC_FREE(br_lck);
3243
3244         if (NT_STATUS_V(status)) {
3245                 reply_nterror(req, status);
3246                 END_PROFILE(SMBlockread);
3247                 return;
3248         }
3249
3250         /*
3251          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3252          */
3253
3254         if (numtoread > sconn->smb1.negprot.max_recv) {
3255                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3256 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3257                         (unsigned int)numtoread,
3258                         (unsigned int)sconn->smb1.negprot.max_recv));
3259                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3260         }
3261         nread = read_file(fsp,data,startpos,numtoread);
3262
3263         if (nread < 0) {
3264                 reply_nterror(req, map_nt_error_from_unix(errno));
3265                 END_PROFILE(SMBlockread);
3266                 return;
3267         }
3268
3269         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3270
3271         SSVAL(req->outbuf,smb_vwv0,nread);
3272         SSVAL(req->outbuf,smb_vwv5,nread+3);
3273         p = smb_buf(req->outbuf);
3274         SCVAL(p,0,0); /* pad byte. */
3275         SSVAL(p,1,nread);
3276
3277         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3278                  fsp->fnum, (int)numtoread, (int)nread));
3279
3280         END_PROFILE(SMBlockread);
3281         return;
3282 }
3283
3284 #undef DBGC_CLASS
3285 #define DBGC_CLASS DBGC_ALL
3286
3287 /****************************************************************************
3288  Reply to a read.
3289 ****************************************************************************/
3290
3291 void reply_read(struct smb_request *req)
3292 {
3293         connection_struct *conn = req->conn;
3294         size_t numtoread;
3295         ssize_t nread = 0;
3296         char *data;
3297         SMB_OFF_T startpos;
3298         int outsize = 0;
3299         files_struct *fsp;
3300         struct lock_struct lock;
3301         struct smbd_server_connection *sconn = smbd_server_conn;
3302
3303         START_PROFILE(SMBread);
3304
3305         if (req->wct < 3) {
3306                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3307                 END_PROFILE(SMBread);
3308                 return;
3309         }
3310
3311         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3312
3313         if (!check_fsp(conn, req, fsp)) {
3314                 END_PROFILE(SMBread);
3315                 return;
3316         }
3317
3318         if (!CHECK_READ(fsp,req)) {
3319                 reply_doserror(req, ERRDOS, ERRbadaccess);
3320                 END_PROFILE(SMBread);
3321                 return;
3322         }
3323
3324         numtoread = SVAL(req->vwv+1, 0);
3325         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3326
3327         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3328
3329         /*
3330          * The requested read size cannot be greater than max_recv. JRA.
3331          */
3332         if (numtoread > sconn->smb1.negprot.max_recv) {
3333                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3334 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3335                         (unsigned int)numtoread,
3336                         (unsigned int)sconn->smb1.negprot.max_recv));
3337                 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3338         }
3339
3340         reply_outbuf(req, 5, numtoread+3);
3341
3342         data = smb_buf(req->outbuf) + 3;
3343
3344         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3345             (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3346             &lock);
3347
3348         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3349                 reply_doserror(req, ERRDOS,ERRlock);
3350                 END_PROFILE(SMBread);
3351                 return;
3352         }
3353
3354         if (numtoread > 0)
3355                 nread = read_file(fsp,data,startpos,numtoread);
3356
3357         if (nread < 0) {
3358                 reply_nterror(req, map_nt_error_from_unix(errno));
3359                 goto strict_unlock;
3360         }
3361
3362         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3363
3364         SSVAL(req->outbuf,smb_vwv0,nread);
3365         SSVAL(req->outbuf,smb_vwv5,nread+3);
3366         SCVAL(smb_buf(req->outbuf),0,1);
3367         SSVAL(smb_buf(req->outbuf),1,nread);
3368
3369         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3370                 fsp->fnum, (int)numtoread, (int)nread ) );
3371
3372 strict_unlock:
3373         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3374
3375         END_PROFILE(SMBread);
3376         return;
3377 }
3378
3379 /****************************************************************************
3380  Setup readX header.
3381 ****************************************************************************/
3382
3383 static int setup_readX_header(struct smb_request *req, char *outbuf,
3384                               size_t smb_maxcnt)
3385 {
3386         int outsize;
3387         char *data;
3388
3389         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3390         data = smb_buf(outbuf);
3391
3392         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3393
3394         SCVAL(outbuf,smb_vwv0,0xFF);
3395         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3396         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3397         SSVAL(outbuf,smb_vwv6,
3398               req_wct_ofs(req)
3399               + 1               /* the wct field */
3400               + 12 * sizeof(uint16_t) /* vwv */
3401               + 2);             /* the buflen field */
3402         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3403         SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3404         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3405         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3406         return outsize;
3407 }
3408
3409 /****************************************************************************
3410  Reply to a read and X - possibly using sendfile.
3411 ****************************************************************************/
3412
3413 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3414                             files_struct *fsp, SMB_OFF_T startpos,
3415                             size_t smb_maxcnt)
3416 {
3417         SMB_STRUCT_STAT sbuf;
3418         ssize_t nread = -1;
3419         struct lock_struct lock;
3420         int saved_errno = 0;
3421
3422         if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3423                 reply_nterror(req, map_nt_error_from_unix(errno));
3424                 return;
3425         }
3426
3427         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3428             (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3429             &lock);
3430
3431         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3432                 reply_doserror(req, ERRDOS, ERRlock);
3433                 return;
3434         }
3435
3436         if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3437             || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3438                 /*
3439                  * We already know that we would do a short read, so don't
3440                  * try the sendfile() path.
3441                  */
3442                 goto nosendfile_read;
3443         }
3444
3445 #if defined(WITH_SENDFILE)
3446         /*
3447          * We can only use sendfile on a non-chained packet
3448          * but we can use on a non-oplocked file. tridge proved this
3449          * on a train in Germany :-). JRA.
3450          */
3451
3452         if (!req_is_in_chain(req) &&
3453             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3454             (fsp->wcp == NULL) &&
3455             lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3456                 uint8 headerbuf[smb_size + 12 * 2];
3457                 DATA_BLOB header;
3458
3459                 /*
3460                  * Set up the packet header before send. We
3461                  * assume here the sendfile will work (get the
3462                  * correct amount of data).
3463                  */
3464
3465                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3466
3467                 construct_reply_common_req(req, (char *)headerbuf);
3468                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3469
3470                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3471                         /* Returning ENOSYS means no data at all was sent.
3472                            Do this as a normal read. */
3473                         if (errno == ENOSYS) {
3474                                 goto normal_read;
3475                         }
3476
3477                         /*
3478                          * Special hack for broken Linux with no working sendfile. If we
3479                          * return EINTR we sent the header but not the rest of the data.
3480                          * Fake this up by doing read/write calls.
3481                          */
3482
3483                         if (errno == EINTR) {
3484                                 /* Ensure we don't do this again. */
3485                                 set_use_sendfile(SNUM(conn), False);
3486                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3487                                 nread = fake_sendfile(fsp, startpos,
3488                                                       smb_maxcnt);
3489                                 if (nread == -1) {
3490                                         DEBUG(0,("send_file_readX: "
3491                                                  "fake_sendfile failed for "
3492                                                  "file %s (%s).\n",
3493                                                  fsp_str_dbg(fsp),
3494                                                  strerror(errno)));
3495                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3496                                 }
3497                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3498                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3499                                 /* No outbuf here means successful sendfile. */
3500                                 goto strict_unlock;
3501                         }
3502
3503                         DEBUG(0,("send_file_readX: sendfile failed for file "
3504                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3505                                  strerror(errno)));
3506                         exit_server_cleanly("send_file_readX sendfile failed");
3507                 } else if (nread == 0) {
3508                         /*
3509                          * Some sendfile implementations return 0 to indicate
3510                          * that there was a short read, but nothing was
3511                          * actually written to the socket.  In this case,
3512                          * fallback to the normal read path so the header gets
3513                          * the correct byte count.
3514                          */
3515                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3516                                   "falling back to the normal read: %s\n",
3517                                   fsp_str_dbg(fsp)));
3518                         goto normal_read;
3519                 }
3520
3521                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3522                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3523
3524                 /* Deal with possible short send. */
3525                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3526                         sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3527                 }
3528                 /* No outbuf here means successful sendfile. */
3529                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3530                 SMB_PERFCOUNT_END(&req->pcd);
3531                 goto strict_unlock;
3532         }
3533
3534 normal_read:
3535
3536 #endif
3537
3538         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3539                 uint8 headerbuf[smb_size + 2*12];
3540
3541                 construct_reply_common_req(req, (char *)headerbuf);
3542                 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3543
3544                 /* Send out the header. */
3545                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3546                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3547                         DEBUG(0,("send_file_readX: write_data failed for file "
3548                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3549                                  strerror(errno)));
3550                         exit_server_cleanly("send_file_readX sendfile failed");
3551                 }
3552                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3553                 if (nread == -1) {
3554                         DEBUG(0,("send_file_readX: fake_sendfile failed for "
3555                                  "file %s (%s).\n", fsp_str_dbg(fsp),
3556                                  strerror(errno)));
3557                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3558                 }
3559                 goto strict_unlock;
3560         }
3561
3562 nosendfile_read:
3563
3564         reply_outbuf(req, 12, smb_maxcnt);
3565
3566         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3567         saved_errno = errno;
3568
3569         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3570
3571         if (nread < 0) {
3572                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3573                 return;
3574         }
3575
3576         setup_readX_header(req, (char *)req->outbuf, nread);
3577
3578         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3579                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3580
3581         chain_reply(req);
3582         return;
3583
3584  strict_unlock:
3585         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3586         TALLOC_FREE(req->outbuf);
3587         return;
3588 }
3589
3590 /****************************************************************************
3591  Reply to a read and X.
3592 ****************************************************************************/
3593
3594 void reply_read_and_X(struct smb_request *req)
3595 {
3596         connection_struct *conn = req->conn;
3597         files_struct *fsp;
3598         SMB_OFF_T startpos;
3599         size_t smb_maxcnt;
3600         bool big_readX = False;
3601 #if 0
3602         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3603 #endif
3604
3605         START_PROFILE(SMBreadX);
3606
3607         if ((req->wct != 10) && (req->wct != 12)) {
3608                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3609                 return;
3610         }
3611
3612         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3613         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3614         smb_maxcnt = SVAL(req->vwv+5, 0);
3615
3616         /* If it's an IPC, pass off the pipe handler. */
3617         if (IS_IPC(conn)) {
3618                 reply_pipe_read_and_X(req);
3619                 END_PROFILE(SMBreadX);
3620                 return;
3621         }
3622
3623         if (!check_fsp(conn, req, fsp)) {
3624                 END_PROFILE(SMBreadX);
3625                 return;
3626         }
3627
3628         if (!CHECK_READ(fsp,req)) {
3629                 reply_doserror(req, ERRDOS,ERRbadaccess);
3630                 END_PROFILE(SMBreadX);
3631                 return;
3632         }
3633
3634         if (global_client_caps & CAP_LARGE_READX) {
3635                 size_t upper_size = SVAL(req->vwv+7, 0);
3636                 smb_maxcnt |= (upper_size<<16);
3637                 if (upper_size > 1) {
3638                         /* Can't do this on a chained packet. */
3639                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3640                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3641                                 END_PROFILE(SMBreadX);
3642                                 return;
3643                         }
3644                         /* We currently don't do this on signed or sealed data. */
3645                         if (srv_is_signing_active(smbd_server_conn) ||
3646                             is_encrypted_packet(req->inbuf)) {
3647                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3648                                 END_PROFILE(SMBreadX);
3649                                 return;
3650                         }
3651                         /* Is there room in the reply for this data ? */
3652                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3653                                 reply_nterror(req,
3654                                               NT_STATUS_INVALID_PARAMETER);
3655                                 END_PROFILE(SMBreadX);
3656                                 return;
3657                         }
3658                         big_readX = True;
3659                 }
3660         }
3661
3662         if (req->wct == 12) {
3663 #ifdef LARGE_SMB_OFF_T
3664                 /*
3665                  * This is a large offset (64 bit) read.
3666                  */
3667                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3668
3669 #else /* !LARGE_SMB_OFF_T */
3670
3671                 /*
3672                  * Ensure we haven't been sent a >32 bit offset.
3673                  */
3674
3675                 if(IVAL(req->vwv+10, 0) != 0) {
3676                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3677                                  "used and we don't support 64 bit offsets.\n",
3678                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3679                         END_PROFILE(SMBreadX);
3680                         reply_doserror(req, ERRDOS, ERRbadaccess);
3681                         return;
3682                 }
3683
3684 #endif /* LARGE_SMB_OFF_T */
3685
3686         }
3687
3688         if (!big_readX &&
3689             schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3690                 goto out;
3691         }
3692
3693         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3694
3695  out:
3696         END_PROFILE(SMBreadX);
3697         return;
3698 }
3699
3700 /****************************************************************************
3701  Error replies to writebraw must have smb_wct == 1. Fix this up.
3702 ****************************************************************************/
3703
3704 void error_to_writebrawerr(struct smb_request *req)
3705 {
3706         uint8 *old_outbuf = req->outbuf;
3707
3708         reply_outbuf(req, 1, 0);
3709
3710         memcpy(req->outbuf, old_outbuf, smb_size);
3711         TALLOC_FREE(old_outbuf);
3712 }
3713
3714 /****************************************************************************
3715  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3716 ****************************************************************************/
3717
3718 void reply_writebraw(struct smb_request *req)
3719 {
3720         connection_struct *conn = req->conn;
3721         char *buf = NULL;
3722         ssize_t nwritten=0;
3723         ssize_t total_written=0;
3724         size_t numtowrite=0;
3725         size_t tcount;
3726         SMB_OFF_T startpos;
3727         char *data=NULL;
3728         bool write_through;
3729         files_struct *fsp;
3730         struct lock_struct lock;
3731         NTSTATUS status;
3732
3733         START_PROFILE(SMBwritebraw);
3734
3735         /*
3736          * If we ever reply with an error, it must have the SMB command
3737          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3738          * we're finished.
3739          */
3740         SCVAL(req->inbuf,smb_com,SMBwritec);
3741
3742         if (srv_is_signing_active(smbd_server_conn)) {
3743                 END_PROFILE(SMBwritebraw);
3744                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3745                                 "raw reads/writes are disallowed.");
3746         }
3747
3748         if (req->wct < 12) {
3749                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3750                 error_to_writebrawerr(req);
3751                 END_PROFILE(SMBwritebraw);
3752                 return;
3753         }
3754
3755         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3756         if (!check_fsp(conn, req, fsp)) {
3757                 error_to_writebrawerr(req);
3758                 END_PROFILE(SMBwritebraw);
3759                 return;
3760         }
3761
3762         if (!CHECK_WRITE(fsp)) {
3763                 reply_doserror(req, ERRDOS, ERRbadaccess);
3764                 error_to_writebrawerr(req);
3765                 END_PROFILE(SMBwritebraw);
3766                 return;
3767         }
3768
3769         tcount = IVAL(req->vwv+1, 0);
3770         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3771         write_through = BITSETW(req->vwv+7,0);
3772
3773         /* We have to deal with slightly different formats depending
3774                 on whether we are using the core+ or lanman1.0 protocol */
3775
3776         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3777                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3778                 data = smb_buf(req->inbuf);
3779         } else {
3780                 numtowrite = SVAL(req->vwv+10, 0);
3781                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3782         }
3783
3784         /* Ensure we don't write bytes past the end of this packet. */
3785         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3786                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3787                 error_to_writebrawerr(req);
3788                 END_PROFILE(SMBwritebraw);
3789                 return;
3790         }
3791
3792         init_strict_lock_struct(fsp, (uint32)req->smbpid,
3793             (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3794             &lock);
3795
3796         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3797                 reply_doserror(req, ERRDOS, ERRlock);
3798                 error_to_writebrawerr(req);
3799                 END_PROFILE(SMBwritebraw);
3800                 return;
3801         }
3802
3803         if (numtowrite>0) {
3804                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3805         }
3806
3807         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3808                         "wrote=%d sync=%d\n",
3809                 fsp->fnum, (double)startpos, (int)numtowrite,
3810                 (int)nwritten, (int)write_through));
3811
3812         if (nwritten < (ssize_t)numtowrite)  {
3813                 reply_doserror(req, ERRHRD, ERRdiskfull);
3814                 error_to_writebrawerr(req);
3815                 goto strict_unlock;
3816         }
3817
3818         total_written = nwritten;
3819
3820         /* Allocate a buffer of 64k + length. */
3821         buf = TALLOC_ARRAY(NULL, char, 65540);
3822         if (!buf) {
3823                 reply_doserror(req, ERRDOS, ERRnomem);
3824                 error_to_writebrawerr(req);
3825                 goto strict_unlock;
3826         }
3827
3828         /* Return a SMBwritebraw message to the redirector to tell
3829          * it to send more bytes */
3830
3831         memcpy(buf, req->inbuf, smb_size);
3832         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3833         SCVAL(buf,smb_com,SMBwritebraw);
3834         SSVALS(buf,smb_vwv0,0xFFFF);
3835         show_msg(buf);
3836         if (!srv_send_smb(smbd_server_fd(),
3837                           buf,
3838                           false, 0, /* no signing */
3839                           IS_CONN_ENCRYPTED(conn),
3840                           &req->pcd)) {
3841                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3842                         "failed.");
3843         }
3844
3845         /* Now read the raw data into the buffer and write it */
3846         status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3847                                  &numtowrite);
3848         if (!NT_STATUS_IS_OK(status)) {
3849                 exit_server_cleanly("secondary writebraw failed");
3850         }
3851
3852         /* Set up outbuf to return the correct size */
3853         reply_outbuf(req, 1, 0);
3854
3855         if (numtowrite != 0) {
3856
3857                 if (numtowrite > 0xFFFF) {
3858                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3859                                 "raw requested (%u). Terminating\n",
3860                                 (unsigned int)numtowrite ));
3861                         exit_server_cleanly("secondary writebraw failed");
3862                 }
3863
3864                 if (tcount > nwritten+numtowrite) {
3865                         DEBUG(3,("reply_writebraw: Client overestimated the "
3866                                 "write %d %d %d\n",
3867                                 (int)tcount,(int)nwritten,(int)numtowrite));
3868                 }
3869
3870                 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3871
3872                 if (!NT_STATUS_IS_OK(status)) {
3873                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3874                                  "raw read failed (%s). Terminating\n",
3875                                  nt_errstr(status)));
3876                         exit_server_cleanly("secondary writebraw failed");
3877                 }
3878
3879                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3880                 if (nwritten == -1) {
3881                         TALLOC_FREE(buf);
3882                         reply_nterror(req, map_nt_error_from_unix(errno));
3883                         error_to_writebrawerr(req);
3884                         goto strict_unlock;
3885                 }
3886
3887                 if (nwritten < (ssize_t)numtowrite) {
3888                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3889                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3890                 }
3891
3892                 if (nwritten > 0) {
3893                         total_written += nwritten;
3894                 }
3895         }
3896
3897         TALLOC_FREE(buf);
3898         SSVAL(req->outbuf,smb_vwv0,total_written);
3899
3900         status = sync_file(conn, fsp, write_through);
3901         if (!NT_STATUS_IS_OK(status)) {
3902                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3903                          fsp_str_dbg(fsp), nt_errstr(status)));
3904                 reply_nterror(req, status);
3905                 error_to_writebrawerr(req);
3906                 goto strict_unlock;
3907         }
3908
3909         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3910                 "wrote=%d\n",
3911                 fsp->fnum, (double)startpos, (int)numtowrite,
3912                 (int)total_written));
3913
3914         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3915
3916         /* We won't return a status if write through is not selected - this
3917          * follows what WfWg does */
3918         END_PROFILE(SMBwritebraw);
3919
3920         if (!write_through && total_written==tcount) {
3921
3922 #if RABBIT_PELLET_FIX
3923                 /*
3924                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3925                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3926                  * JRA.
3927                  */
3928                 if (!send_keepalive(smbd_server_fd())) {
3929                         exit_server_cleanly("reply_writebraw: send of "
3930                                 "keepalive failed");
3931                 }
3932 #endif
3933                 TALLOC_FREE(req->outbuf);
3934         }
3935         return;
3936
3937 strict_unlock:
3938         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3939
3940         END_PROFILE(SMBwritebraw);
3941         return;
3942 }
3943
3944 #undef DBGC_CLASS
3945 #define DBGC_CLASS DBGC_LOCKING
3946
3947 /****************************************************************************
3948  Reply to a writeunlock (core+).
3949 ****************************************************************************/
3950
3951 void reply_writeunlock(struct smb_request *req)
3952 {
3953         connection_struct *conn = req->conn;
3954         ssize_t nwritten = -1;
3955         size_t numtowrite;
3956         SMB_OFF_T startpos;
3957         const char *data;
3958         NTSTATUS status = NT_STATUS_OK;
3959         files_struct *fsp;
3960         struct lock_struct lock;
3961         int saved_errno = 0;
3962
3963         START_PROFILE(SMBwriteunlock);
3964
3965         if (req->wct < 5) {
3966                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3967                 END_PROFILE(SMBwriteunlock);
3968                 return;
3969         }
3970
3971         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3972
3973         if (!check_fsp(conn, req, fsp)) {
3974                 END_PROFILE(SMBwriteunlock);
3975                 return;
3976         }
3977
3978         if (!CHECK_WRITE(fsp)) {
3979                 reply_doserror(req, ERRDOS,ERRbadaccess);
3980                 END_PROFILE(SMBwriteunlock);
3981                 return;
3982         }
3983
3984         numtowrite = SVAL(req->vwv+1, 0);
3985         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3986         data = (const char *)req->buf + 3;
3987
3988         if (numtowrite) {
3989                 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3990                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3991                     &lock);
3992
3993                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3994                         reply_doserror(req, ERRDOS, ERRlock);
3995                         END_PROFILE(SMBwriteunlock);
3996                         return;
3997                 }
3998         }
3999
4000         /* The special X/Open SMB protocol handling of
4001            zero length writes is *NOT* done for
4002            this call */
4003         if(numtowrite == 0) {
4004                 nwritten = 0;
4005         } else {
4006                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4007                 saved_errno = errno;
4008         }
4009
4010         status = sync_file(conn, fsp, False /* write through */);
4011         if (!NT_STATUS_IS_OK(status)) {
4012                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4013                          fsp_str_dbg(fsp), nt_errstr(status)));
4014                 reply_nterror(req, status);
4015                 goto strict_unlock;
4016         }
4017
4018         if(nwritten < 0) {
4019                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4020                 goto strict_unlock;
4021         }
4022
4023         if((nwritten < numtowrite) && (numtowrite != 0)) {
4024                 reply_doserror(req, ERRHRD, ERRdiskfull);
4025                 goto strict_unlock;
4026         }
4027
4028         if (numtowrite) {
4029                 status = do_unlock(smbd_messaging_context(),
4030                                 fsp,
4031                                 req->smbpid,
4032                                 (uint64_t)numtowrite, 
4033                                 (uint64_t)startpos,
4034                                 WINDOWS_LOCK);
4035
4036                 if (NT_STATUS_V(status)) {
4037                         reply_nterror(req, status);
4038                         goto strict_unlock;
4039                 }
4040         }
4041
4042         reply_outbuf(req, 1, 0);
4043
4044         SSVAL(req->outbuf,smb_vwv0,nwritten);
4045
4046         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4047                  fsp->fnum, (int)numtowrite, (int)nwritten));
4048
4049 strict_unlock:
4050         if (numtowrite) {
4051                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4052         }
4053
4054         END_PROFILE(SMBwriteunlock);
4055         return;
4056 }
4057
4058 #undef DBGC_CLASS
4059 #define DBGC_CLASS DBGC_ALL
4060
4061 /****************************************************************************
4062  Reply to a write.
4063 ****************************************************************************/
4064
4065 void reply_write(struct smb_request *req)
4066 {
4067         connection_struct *conn = req->conn;
4068         size_t numtowrite;
4069         ssize_t nwritten = -1;
4070         SMB_OFF_T startpos;
4071         const char *data;
4072         files_struct *fsp;
4073         struct lock_struct lock;
4074         NTSTATUS status;
4075         int saved_errno = 0;
4076
4077         START_PROFILE(SMBwrite);
4078
4079         if (req->wct < 5) {
4080                 END_PROFILE(SMBwrite);
4081                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4082                 return;
4083         }
4084
4085         /* If it's an IPC, pass off the pipe handler. */
4086         if (IS_IPC(conn)) {
4087                 reply_pipe_write(req);
4088                 END_PROFILE(SMBwrite);
4089                 return;
4090         }
4091
4092         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4093
4094         if (!check_fsp(conn, req, fsp)) {
4095                 END_PROFILE(SMBwrite);
4096                 return;
4097         }
4098
4099         if (!CHECK_WRITE(fsp)) {
4100                 reply_doserror(req, ERRDOS, ERRbadaccess);
4101                 END_PROFILE(SMBwrite);
4102                 return;
4103         }
4104
4105         numtowrite = SVAL(req->vwv+1, 0);
4106         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4107         data = (const char *)req->buf + 3;
4108
4109         init_strict_lock_struct(fsp, (uint32)req->smbpid,
4110             (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4111             &lock);
4112
4113         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4114                 reply_doserror(req, ERRDOS, ERRlock);
4115                 END_PROFILE(SMBwrite);
4116                 return;
4117         }
4118
4119         /*
4120          * X/Open SMB protocol says that if smb_vwv1 is
4121          * zero then the file size should be extended or
4122          * truncated to the size given in smb_vwv[2-3].
4123          */
4124
4125         if(numtowrite == 0) {
4126                 /*
4127                  * This is actually an allocate call, and set EOF. JRA.
4128                  */
4129                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4130                 if (nwritten < 0) {
4131                         reply_nterror(req, NT_STATUS_DISK_FULL);
4132                         goto strict_unlock;
4133                 }
4134                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4135                 if (nwritten < 0) {
4136                         reply_nterror(req, NT_STATUS_DISK_FULL);
4137                         goto strict_unlock;
4138                 }
4139                 trigger_write_time_update_immediate(fsp);
4140         } else {
4141                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4142         }
4143
4144         status = sync_file(conn, fsp, False);
4145         if (!NT_STATUS_IS_OK(status)) {
4146                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4147                          fsp_str_dbg(fsp), nt_errstr(status)));
4148                 reply_nterror(req, status);
4149                 goto strict_unlock;
4150         }
4151
4152         if(nwritten < 0) {
4153                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4154                 goto strict_unlock;
4155         }
4156
4157         if((nwritten == 0) && (numtowrite != 0)) {
4158                 reply_doserror(req, ERRHRD, ERRdiskfull);
4159                 goto strict_unlock;
4160         }
4161
4162         reply_outbuf(req, 1, 0);
4163
4164         SSVAL(req->outbuf,smb_vwv0,nwritten);
4165
4166         if (nwritten < (ssize_t)numtowrite) {
4167                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4168                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4169         }
4170
4171         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4172
4173 strict_unlock:
4174         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4175
4176         END_PROFILE(SMBwrite);
4177         return;
4178 }
4179
4180 /****************************************************************************
4181  Ensure a buffer is a valid writeX for recvfile purposes.
4182 ****************************************************************************/
4183
4184 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4185                                                 (2*14) + /* word count (including bcc) */ \
4186                                                 1 /* pad byte */)
4187
4188 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4189 {
4190         size_t numtowrite;
4191         connection_struct *conn = NULL;
4192         unsigned int doff = 0;
4193         size_t len = smb_len_large(inbuf);
4194         struct smbd_server_connection *sconn = smbd_server_conn;
4195
4196         if (is_encrypted_packet(inbuf)) {
4197                 /* Can't do this on encrypted
4198                  * connections. */
4199                 return false;
4200         }
4201
4202         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4203                 return false;
4204         }
4205
4206         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4207                         CVAL(inbuf,smb_wct) != 14) {
4208                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4209                         "invalid word length.\n"));
4210                 return false;
4211         }
4212
4213         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4214         if (conn == NULL) {
4215                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4216                 return false;
4217         }
4218         if (IS_IPC(conn)) {
4219                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4220                 return false;
4221         }
4222         if (IS_PRINT(conn)) {
4223                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4224                 return false;
4225         }
4226         doff = SVAL(inbuf,smb_vwv11);
4227
4228         numtowrite = SVAL(inbuf,smb_vwv10);
4229
4230         if (len > doff && len - doff > 0xFFFF) {
4231                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4232         }
4233
4234         if (numtowrite == 0) {
4235                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4236                 return false;
4237         }
4238
4239         /* Ensure the sizes match up. */
4240         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4241                 /* no pad byte...old smbclient :-( */
4242                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4243                         (unsigned int)doff,
4244                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4245                 return false;
4246         }
4247
4248         if (len - doff != numtowrite) {
4249                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4250                         "len = %u, doff = %u, numtowrite = %u\n",
4251                         (unsigned int)len,
4252                         (unsigned int)doff,
4253                         (unsigned int)numtowrite ));
4254                 return false;
4255         }
4256
4257         DEBUG(10,("is_valid_writeX_buffer: true "
4258                 "len = %u, doff = %u, numtowrite = %u\n",
4259                 (unsigned int)len,
4260                 (unsigned int)doff,
4261                 (unsigned int)numtowrite ));
4262
4263         return true;
4264 }
4265
4266 /****************************************************************************
4267  Reply to a write and X.
4268 ****************************************************************************/
4269
4270 void reply_write_and_X(struct smb_request *req)
4271 {
4272         connection_struct *conn = req->conn;
4273         files_struct *fsp;
4274         struct lock_struct lock;
4275         SMB_OFF_T startpos;
4276         size_t numtowrite;
4277         bool write_through;
4278         ssize_t nwritten;
4279         unsigned int smb_doff;
4280         unsigned int smblen;
4281         char *data;
4282         NTSTATUS status;
4283
4284         START_PROFILE(SMBwriteX);
4285
4286         if ((req->wct != 12) && (req->wct != 14)) {
4287                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4288                 END_PROFILE(SMBwriteX);
4289                 return;
4290         }
4291
4292         numtowrite = SVAL(req->vwv+10, 0);
4293         smb_doff = SVAL(req->vwv+11, 0);
4294         smblen = smb_len(req->inbuf);
4295
4296         if (req->unread_bytes > 0xFFFF ||
4297                         (smblen > smb_doff &&
4298                                 smblen - smb_doff > 0xFFFF)) {
4299                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4300         }
4301
4302         if (req->unread_bytes) {
4303                 /* Can't do a recvfile write on IPC$ */
4304                 if (IS_IPC(conn)) {
4305                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4306                         END_PROFILE(SMBwriteX);
4307                         return;
4308                 }
4309                 if (numtowrite != req->unread_bytes) {
4310                         reply_doserror(req, ERRDOS, ERRbadmem);
4311                         END_PROFILE(SMBwriteX);
4312                         return;
4313                 }
4314         } else {
4315                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4316                                 smb_doff + numtowrite > smblen) {
4317                         reply_doserror(req, ERRDOS, ERRbadmem);
4318                         END_PROFILE(SMBwriteX);
4319                         return;
4320                 }
4321         }
4322
4323         /* If it's an IPC, pass off the pipe handler. */
4324         if (IS_IPC(conn)) {
4325                 if (req->unread_bytes) {
4326                         reply_doserror(req, ERRDOS, ERRbadmem);
4327                         END_PROFILE(SMBwriteX);
4328                         return;
4329                 }
4330                 reply_pipe_write_and_X(req);
4331                 END_PROFILE(SMBwriteX);
4332                 return;
4333         }
4334
4335         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4336         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4337         write_through = BITSETW(req->vwv+7,0);
4338
4339         if (!check_fsp(conn, req, fsp)) {
4340                 END_PROFILE(SMBwriteX);
4341                 return;
4342         }
4343
4344         if (!CHECK_WRITE(fsp)) {
4345                 reply_doserror(req, ERRDOS, ERRbadaccess);
4346                 END_PROFILE(SMBwriteX);
4347                 return;
4348         }
4349
4350         data = smb_base(req->inbuf) + smb_doff;
4351
4352         if(req->wct == 14) {
4353 #ifdef LARGE_SMB_OFF_T
4354                 /*
4355                  * This is a large offset (64 bit) write.
4356                  */
4357                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4358
4359 #else /* !LARGE_SMB_OFF_T */
4360
4361                 /*
4362                  * Ensure we haven't been sent a >32 bit offset.
4363                  */
4364
4365                 if(IVAL(req->vwv+12, 0) != 0) {
4366                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4367                                  "used and we don't support 64 bit offsets.\n",
4368                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4369                         reply_doserror(req, ERRDOS, ERRbadaccess);
4370                         END_PROFILE(SMBwriteX);
4371                         return;
4372                 }
4373
4374 #endif /* LARGE_SMB_OFF_T */
4375         }
4376
4377         init_strict_lock_struct(fsp, (uint32)req->smbpid,
4378             (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4379             &lock);
4380
4381         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4382                 reply_doserror(req, ERRDOS, ERRlock);
4383                 END_PROFILE(SMBwriteX);
4384                 return;
4385         }
4386
4387         /* X/Open SMB protocol says that, unlike SMBwrite
4388         if the length is zero then NO truncation is
4389         done, just a write of zero. To truncate a file,
4390         use SMBwrite. */
4391
4392         if(numtowrite == 0) {
4393                 nwritten = 0;
4394         } else {
4395
4396                 if ((req->unread_bytes == 0) &&
4397                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4398                                              numtowrite)) {
4399                         goto strict_unlock;
4400                 }
4401
4402                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4403         }
4404
4405         if(nwritten < 0) {
4406                 reply_nterror(req, map_nt_error_from_unix(errno));
4407                 goto strict_unlock;
4408         }
4409
4410         if((nwritten == 0) && (numtowrite != 0)) {
4411                 reply_doserror(req, ERRHRD, ERRdiskfull);
4412                 goto strict_unlock;
4413         }
4414
4415         reply_outbuf(req, 6, 0);
4416         SSVAL(req->outbuf,smb_vwv2,nwritten);
4417         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4418
4419         if (nwritten < (ssize_t)numtowrite) {
4420                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4421                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4422         }
4423
4424         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4425                 fsp->fnum, (int)numtowrite, (int)nwritten));
4426
4427         status = sync_file(conn, fsp, write_through);
4428         if (!NT_STATUS_IS_OK(status)) {
4429                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4430                          fsp_str_dbg(fsp), nt_errstr(status)));
4431                 reply_nterror(req, status);
4432                 goto strict_unlock;
4433         }
4434
4435         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4436
4437         END_PROFILE(SMBwriteX);
4438         chain_reply(req);
4439         return;
4440
4441 strict_unlock:
4442         SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4443
4444         END_PROFILE(SMBwriteX);
4445         return;
4446 }
4447
4448 /****************************************************************************
4449  Reply to a lseek.
4450 ****************************************************************************/
4451
4452 void reply_lseek(struct smb_request *req)
4453 {
4454         connection_struct *conn = req->conn;
4455         SMB_OFF_T startpos;
4456         SMB_OFF_T res= -1;
4457         int mode,umode;
4458         files_struct *fsp;
4459
4460         START_PROFILE(SMBlseek);
4461
4462         if (req->wct < 4) {
4463                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4464                 END_PROFILE(SMBlseek);
4465                 return;
4466         }
4467
4468         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4469
4470         if (!check_fsp(conn, req, fsp)) {
4471                 return;
4472         }
4473
4474         flush_write_cache(fsp, SEEK_FLUSH);
4475
4476         mode = SVAL(req->vwv+1, 0) & 3;
4477         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4478         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4479
4480         switch (mode) {
4481                 case 0:
4482                         umode = SEEK_SET;
4483                         res = startpos;
4484                         break;
4485                 case 1:
4486                         umode = SEEK_CUR;
4487                         res = fsp->fh->pos + startpos;
4488                         break;
4489                 case 2:
4490                         umode = SEEK_END;
4491                         break;
4492                 default:
4493                         umode = SEEK_SET;
4494                         res = startpos;
4495                         break;
4496         }
4497
4498         if (umode == SEEK_END) {
4499                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4500                         if(errno == EINVAL) {
4501                                 SMB_OFF_T current_pos = startpos;
4502                                 SMB_STRUCT_STAT sbuf;
4503
4504                                 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4505                                         reply_nterror(req,
4506                                                 map_nt_error_from_unix(errno));
4507                                         END_PROFILE(SMBlseek);
4508                                         return;
4509                                 }
4510
4511                                 current_pos += sbuf.st_ex_size;
4512                                 if(current_pos < 0)
4513                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4514                         }
4515                 }
4516
4517                 if(res == -1) {
4518                         reply_nterror(req, map_nt_error_from_unix(errno));
4519                         END_PROFILE(SMBlseek);
4520                         return;
4521                 }
4522         }
4523
4524         fsp->fh->pos = res;
4525
4526         reply_outbuf(req, 2, 0);
4527         SIVAL(req->outbuf,smb_vwv0,res);
4528
4529         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4530                 fsp->fnum, (double)startpos, (double)res, mode));
4531
4532         END_PROFILE(SMBlseek);
4533         return;
4534 }
4535
4536 /****************************************************************************
4537  Reply to a flush.
4538 ****************************************************************************/
4539
4540 void reply_flush(struct smb_request *req)
4541 {
4542         connection_struct *conn = req->conn;
4543         uint16 fnum;
4544         files_struct *fsp;
4545
4546         START_PROFILE(SMBflush);
4547
4548         if (req->wct < 1) {
4549                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4550                 return;
4551         }
4552
4553         fnum = SVAL(req->vwv+0, 0);
4554         fsp = file_fsp(req, fnum);
4555
4556         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4557                 return;
4558         }
4559
4560         if (!fsp) {
4561                 file_sync_all(conn);
4562         } else {
4563                 NTSTATUS status = sync_file(conn, fsp, True);
4564                 if (!NT_STATUS_IS_OK(status)) {
4565                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4566                                 fsp_str_dbg(fsp), nt_errstr(status)));
4567                         reply_nterror(req, status);
4568                         END_PROFILE(SMBflush);
4569                         return;
4570                 }
4571         }
4572
4573         reply_outbuf(req, 0, 0);
4574
4575         DEBUG(3,("flush\n"));
4576         END_PROFILE(SMBflush);
4577         return;
4578 }
4579
4580 /****************************************************************************
4581  Reply to a exit.
4582  conn POINTER CAN BE NULL HERE !
4583 ****************************************************************************/
4584
4585 void reply_exit(struct smb_request *req)
4586 {
4587         START_PROFILE(SMBexit);
4588
4589         file_close_pid(req->smbpid, req->vuid);
4590
4591         reply_outbuf(req, 0, 0);
4592
4593         DEBUG(3,("exit\n"));
4594
4595         END_PROFILE(SMBexit);
4596         return;
4597 }
4598
4599 /****************************************************************************
4600  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4601 ****************************************************************************/
4602
4603 void reply_close(struct smb_request *req)
4604 {
4605         connection_struct *conn = req->conn;
4606         NTSTATUS status = NT_STATUS_OK;
4607         files_struct *fsp = NULL;
4608         START_PROFILE(SMBclose);
4609
4610         if (req->wct < 3) {
4611                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4612                 END_PROFILE(SMBclose);
4613                 return;
4614         }
4615
4616         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4617
4618         /*
4619          * We can only use check_fsp if we know it's not a directory.
4620          */
4621
4622         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4623                 reply_doserror(req, ERRDOS, ERRbadfid);
4624                 END_PROFILE(SMBclose);
4625                 return;
4626         }
4627
4628         if(fsp->is_directory) {
4629                 /*
4630                  * Special case - close NT SMB directory handle.
4631                  */
4632                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4633                 status = close_file(req, fsp, NORMAL_CLOSE);
4634         } else {
4635                 time_t t;
4636                 /*
4637                  * Close ordinary file.
4638                  */
4639
4640                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4641                          fsp->fh->fd, fsp->fnum,
4642                          conn->num_files_open));
4643
4644                 /*
4645                  * Take care of any time sent in the close.
4646                  */
4647
4648                 t = srv_make_unix_date3(req->vwv+1);
4649                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4650
4651                 /*
4652                  * close_file() returns the unix errno if an error
4653                  * was detected on close - normally this is due to
4654                  * a disk full error. If not then it was probably an I/O error.
4655                  */
4656
4657                 status = close_file(req, fsp, NORMAL_CLOSE);
4658         }  
4659
4660         if (!NT_STATUS_IS_OK(status)) {
4661                 reply_nterror(req, status);
4662                 END_PROFILE(SMBclose);
4663                 return;
4664         }
4665
4666         reply_outbuf(req, 0, 0);
4667         END_PROFILE(SMBclose);
4668         return;
4669 }
4670
4671 /****************************************************************************
4672  Reply to a writeclose (Core+ protocol).
4673 ****************************************************************************/
4674
4675 void reply_writeclose(struct smb_request *req)
4676 {
4677         connection_struct *conn = req->conn;
4678         size_t numtowrite;
4679         ssize_t nwritten = -1;
4680         NTSTATUS close_status = NT_STATUS_OK;
4681         SMB_OFF_T startpos;
4682         const char *data;
4683         struct timespec mtime;
4684         files_struct *fsp;
4685         struct lock_struct lock;
4686
4687         START_PROFILE(SMBwriteclose);
4688
4689         if (req->wct < 6) {
4690                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4691                 END_PROFILE(SMBwriteclose);
4692                 return;
4693         }
4694
4695         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4696
4697         if (!check_fsp(conn, req, fsp)) {
4698                 END_PROFILE(SMBwriteclose);
4699                 return;
4700         }
4701         if (!CHECK_WRITE(fsp)) {
4702                 reply_doserror(req, ERRDOS,ERRbadaccess);
4703                 END_PROFILE(SMBwriteclose);
4704                 return;
4705         }
4706
4707         numtowrite = SVAL(req->vwv+1, 0);
4708         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4709         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4710         data = (const char *)req->buf + 1;
4711
4712         if (numtowrite) {
4713                 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4714                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4715                     &lock);
4716
4717                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4718                         reply_doserror(req, ERRDOS,ERRlock);
4719                         END_PROFILE(SMBwriteclose);
4720                         return;
4721                 }
4722         }
4723
4724         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4725
4726         set_close_write_time(fsp, mtime);
4727
4728         /*
4729          * More insanity. W2K only closes the file if writelen > 0.
4730          * JRA.
4731          */
4732
4733         if (numtowrite) {
4734                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4735                          "file %s\n", fsp_str_dbg(fsp)));
4736                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4737         }
4738
4739         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4740                  fsp->fnum, (int)numtowrite, (int)nwritten,
4741                  conn->num_files_open));
4742
4743         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4744                 reply_doserror(req, ERRHRD, ERRdiskfull);
4745                 goto strict_unlock;
4746         }
4747
4748         if(!NT_STATUS_IS_OK(close_status)) {
4749                 reply_nterror(req, close_status);
4750                 goto strict_unlock;
4751         }
4752
4753         reply_outbuf(req, 1, 0);
4754
4755         SSVAL(req->outbuf,smb_vwv0,nwritten);
4756
4757 strict_unlock:
4758         if (numtowrite) {
4759                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4760         }
4761
4762         END_PROFILE(SMBwriteclose);
4763         return;
4764 }
4765
4766 #undef DBGC_CLASS
4767 #define DBGC_CLASS DBGC_LOCKING
4768
4769 /****************************************************************************
4770  Reply to a lock.
4771 ****************************************************************************/
4772
4773 void reply_lock(struct smb_request *req)
4774 {
4775         connection_struct *conn = req->conn;
4776         uint64_t count,offset;
4777         NTSTATUS status;
4778         files_struct *fsp;
4779         struct byte_range_lock *br_lck = NULL;
4780
4781         START_PROFILE(SMBlock);
4782
4783         if (req->wct < 5) {
4784                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4785                 END_PROFILE(SMBlock);
4786                 return;
4787         }
4788
4789         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4790
4791         if (!check_fsp(conn, req, fsp)) {
4792                 END_PROFILE(SMBlock);
4793                 return;
4794         }
4795
4796         count = (uint64_t)IVAL(req->vwv+1, 0);
4797         offset = (uint64_t)IVAL(req->vwv+3, 0);
4798
4799         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4800                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4801
4802         br_lck = do_lock(smbd_messaging_context(),
4803                         fsp,
4804                         req->smbpid,
4805                         count,
4806                         offset,
4807                         WRITE_LOCK,
4808                         WINDOWS_LOCK,
4809                         False, /* Non-blocking lock. */
4810                         &status,
4811                         NULL,
4812                         NULL);
4813
4814         TALLOC_FREE(br_lck);
4815
4816         if (NT_STATUS_V(status)) {
4817                 reply_nterror(req, status);
4818                 END_PROFILE(SMBlock);
4819                 return;
4820         }
4821
4822         reply_outbuf(req, 0, 0);
4823
4824         END_PROFILE(SMBlock);
4825         return;
4826 }
4827
4828 /****************************************************************************
4829  Reply to a unlock.
4830 ****************************************************************************/
4831
4832 void reply_unlock(struct smb_request *req)
4833 {
4834         connection_struct *conn = req->conn;
4835         uint64_t count,offset;
4836         NTSTATUS status;
4837         files_struct *fsp;
4838
4839         START_PROFILE(SMBunlock);
4840
4841         if (req->wct < 5) {
4842                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4843                 END_PROFILE(SMBunlock);
4844                 return;
4845         }
4846
4847         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4848
4849         if (!check_fsp(conn, req, fsp)) {
4850                 END_PROFILE(SMBunlock);
4851                 return;
4852         }
4853
4854         count = (uint64_t)IVAL(req->vwv+1, 0);
4855         offset = (uint64_t)IVAL(req->vwv+3, 0);
4856
4857         status = do_unlock(smbd_messaging_context(),
4858                         fsp,
4859                         req->smbpid,
4860                         count,
4861                         offset,
4862                         WINDOWS_LOCK);
4863
4864         if (NT_STATUS_V(status)) {
4865                 reply_nterror(req, status);
4866                 END_PROFILE(SMBunlock);
4867                 return;
4868         }
4869
4870         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4871                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4872
4873         reply_outbuf(req, 0, 0);
4874
4875         END_PROFILE(SMBunlock);
4876         return;
4877 }
4878
4879 #undef DBGC_CLASS
4880 #define DBGC_CLASS DBGC_ALL
4881
4882 /****************************************************************************
4883  Reply to a tdis.
4884  conn POINTER CAN BE NULL HERE !
4885 ****************************************************************************/
4886
4887 void reply_tdis(struct smb_request *req)
4888 {
4889         connection_struct *conn = req->conn;
4890         START_PROFILE(SMBtdis);
4891
4892         if (!conn) {
4893                 DEBUG(4,("Invalid connection in tdis\n"));
4894                 reply_doserror(req, ERRSRV, ERRinvnid);
4895                 END_PROFILE(SMBtdis);
4896                 return;
4897         }
4898
4899         conn->used = False;
4900
4901         close_cnum(conn,req->vuid);
4902         req->conn = NULL;
4903
4904         reply_outbuf(req, 0, 0);
4905         END_PROFILE(SMBtdis);
4906         return;
4907 }
4908
4909 /****************************************************************************
4910  Reply to a echo.
4911  conn POINTER CAN BE NULL HERE !
4912 ****************************************************************************/
4913
4914 void reply_echo(struct smb_request *req)
4915 {
4916         connection_struct *conn = req->conn;
4917         struct smb_perfcount_data local_pcd;
4918         struct smb_perfcount_data *cur_pcd;
4919         int smb_reverb;
4920         int seq_num;
4921
4922         START_PROFILE(SMBecho);
4923
4924         smb_init_perfcount_data(&local_pcd);
4925
4926         if (req->wct < 1) {
4927                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4928                 END_PROFILE(SMBecho);
4929                 return;
4930         }
4931
4932         smb_reverb = SVAL(req->vwv+0, 0);
4933
4934         reply_outbuf(req, 1, req->buflen);
4935
4936         /* copy any incoming data back out */
4937         if (req->buflen > 0) {
4938                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4939         }
4940
4941         if (smb_reverb > 100) {
4942                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4943                 smb_reverb = 100;
4944         }
4945
4946         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4947
4948                 /* this makes sure we catch the request pcd */
4949                 if (seq_num == smb_reverb) {
4950                         cur_pcd = &req->pcd;
4951                 } else {
4952                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4953                         cur_pcd = &local_pcd;
4954                 }
4955
4956                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4957
4958                 show_msg((char *)req->outbuf);
4959                 if (!srv_send_smb(smbd_server_fd(),
4960                                 (char *)req->outbuf,
4961                                 true, req->seqnum+1,
4962                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4963                                 cur_pcd))
4964                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4965         }
4966
4967         DEBUG(3,("echo %d times\n", smb_reverb));
4968
4969         TALLOC_FREE(req->outbuf);
4970
4971         END_PROFILE(SMBecho);
4972         return;
4973 }
4974
4975 /****************************************************************************
4976  Reply to a printopen.
4977 ****************************************************************************/
4978
4979 void reply_printopen(struct smb_request *req)
4980 {
4981         connection_struct *conn = req->conn;
4982         files_struct *fsp;
4983         NTSTATUS status;
4984
4985         START_PROFILE(SMBsplopen);
4986
4987         if (req->wct < 2) {
4988                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4989                 END_PROFILE(SMBsplopen);
4990                 return;
4991         }
4992
4993         if (!CAN_PRINT(conn)) {
4994                 reply_doserror(req, ERRDOS, ERRnoaccess);
4995                 END_PROFILE(SMBsplopen);
4996                 return;
4997         }
4998
4999         status = file_new(req, conn, &fsp);
5000         if(!NT_STATUS_IS_OK(status)) {
5001                 reply_nterror(req, status);
5002                 END_PROFILE(SMBsplopen);
5003                 return;
5004         }
5005
5006         /* Open for exclusive use, write only. */
5007         status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5008
5009         if (!NT_STATUS_IS_OK(status)) {
5010                 file_free(req, fsp);
5011                 reply_nterror(req, status);
5012                 END_PROFILE(SMBsplopen);
5013                 return;
5014         }
5015
5016         reply_outbuf(req, 1, 0);
5017         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5018
5019         DEBUG(3,("openprint fd=%d fnum=%d\n",
5020                  fsp->fh->fd, fsp->fnum));
5021
5022         END_PROFILE(SMBsplopen);
5023         return;
5024 }
5025
5026 /****************************************************************************
5027  Reply to a printclose.
5028 ****************************************************************************/
5029
5030 void reply_printclose(struct smb_request *req)
5031 {
5032         connection_struct *conn = req->conn;
5033         files_struct *fsp;
5034         NTSTATUS status;
5035
5036         START_PROFILE(SMBsplclose);
5037
5038         if (req->wct < 1) {
5039                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5040                 END_PROFILE(SMBsplclose);
5041                 return;
5042         }
5043
5044         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5045
5046         if (!check_fsp(conn, req, fsp)) {
5047                 END_PROFILE(SMBsplclose);
5048                 return;
5049         }
5050
5051         if (!CAN_PRINT(conn)) {
5052                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5053                 END_PROFILE(SMBsplclose);
5054                 return;
5055         }
5056
5057         DEBUG(3,("printclose fd=%d fnum=%d\n",
5058                  fsp->fh->fd,fsp->fnum));
5059
5060         status = close_file(req, fsp, NORMAL_CLOSE);
5061
5062         if(!NT_STATUS_IS_OK(status)) {
5063                 reply_nterror(req, status);
5064                 END_PROFILE(SMBsplclose);
5065                 return;
5066         }
5067
5068         reply_outbuf(req, 0, 0);
5069
5070         END_PROFILE(SMBsplclose);
5071         return;
5072 }
5073
5074 /****************************************************************************
5075  Reply to a printqueue.
5076 ****************************************************************************/
5077
5078 void reply_printqueue(struct smb_request *req)
5079 {
5080         connection_struct *conn = req->conn;
5081         int max_count;
5082         int start_index;
5083
5084         START_PROFILE(SMBsplretq);
5085
5086         if (req->wct < 2) {
5087                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088                 END_PROFILE(SMBsplretq);
5089                 return;
5090         }
5091
5092         max_count = SVAL(req->vwv+0, 0);
5093         start_index = SVAL(req->vwv+1, 0);
5094
5095         /* we used to allow the client to get the cnum wrong, but that
5096            is really quite gross and only worked when there was only
5097            one printer - I think we should now only accept it if they
5098            get it right (tridge) */
5099         if (!CAN_PRINT(conn)) {
5100                 reply_doserror(req, ERRDOS, ERRnoaccess);
5101                 END_PROFILE(SMBsplretq);
5102                 return;
5103         }
5104
5105         reply_outbuf(req, 2, 3);
5106         SSVAL(req->outbuf,smb_vwv0,0);
5107         SSVAL(req->outbuf,smb_vwv1,0);
5108         SCVAL(smb_buf(req->outbuf),0,1);
5109         SSVAL(smb_buf(req->outbuf),1,0);
5110
5111         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5112                  start_index, max_count));
5113
5114         {
5115                 print_queue_struct *queue = NULL;
5116                 print_status_struct status;
5117                 int count = print_queue_status(SNUM(conn), &queue, &status);
5118                 int num_to_get = ABS(max_count);
5119                 int first = (max_count>0?start_index:start_index+max_count+1);
5120                 int i;
5121
5122                 if (first >= count)
5123                         num_to_get = 0;
5124                 else
5125                         num_to_get = MIN(num_to_get,count-first);
5126
5127
5128                 for (i=first;i<first+num_to_get;i++) {
5129                         char blob[28];
5130                         char *p = blob;
5131
5132                         srv_put_dos_date2(p,0,queue[i].time);
5133                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5134                         SSVAL(p,5, queue[i].job);
5135                         SIVAL(p,7,queue[i].size);
5136                         SCVAL(p,11,0);
5137                         srvstr_push(blob, req->flags2, p+12,
5138                                     queue[i].fs_user, 16, STR_ASCII);
5139
5140                         if (message_push_blob(
5141                                     &req->outbuf,
5142                                     data_blob_const(
5143                                             blob, sizeof(blob))) == -1) {
5144                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5145                                 END_PROFILE(SMBsplretq);
5146                                 return;
5147                         }
5148                 }
5149
5150                 if (count > 0) {
5151                         SSVAL(req->outbuf,smb_vwv0,count);
5152                         SSVAL(req->outbuf,smb_vwv1,
5153                               (max_count>0?first+count:first-1));
5154                         SCVAL(smb_buf(req->outbuf),0,1);
5155                         SSVAL(smb_buf(req->outbuf),1,28*count);
5156                 }
5157
5158                 SAFE_FREE(queue);
5159
5160                 DEBUG(3,("%d entries returned in queue\n",count));
5161         }
5162
5163         END_PROFILE(SMBsplretq);
5164         return;
5165 }
5166
5167 /****************************************************************************
5168  Reply to a printwrite.
5169 ****************************************************************************/
5170
5171 void reply_printwrite(struct smb_request *req)
5172 {
5173         connection_struct *conn = req->conn;
5174         int numtowrite;
5175         const char *data;
5176         files_struct *fsp;
5177
5178         START_PROFILE(SMBsplwr);
5179
5180         if (req->wct < 1) {
5181                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5182                 END_PROFILE(SMBsplwr);
5183                 return;
5184         }
5185
5186         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5187
5188         if (!check_fsp(conn, req, fsp)) {
5189                 END_PROFILE(SMBsplwr);
5190                 return;
5191         }
5192
5193         if (!CAN_PRINT(conn)) {
5194                 reply_doserror(req, ERRDOS, ERRnoaccess);
5195                 END_PROFILE(SMBsplwr);
5196                 return;
5197         }
5198
5199         if (!CHECK_WRITE(fsp)) {
5200                 reply_doserror(req, ERRDOS, ERRbadaccess);
5201                 END_PROFILE(SMBsplwr);
5202                 return;
5203         }
5204
5205         numtowrite = SVAL(req->buf, 1);
5206
5207         if (req->buflen < numtowrite + 3) {
5208                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5209                 END_PROFILE(SMBsplwr);
5210                 return;
5211         }
5212
5213         data = (const char *)req->buf + 3;
5214
5215         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5216                 reply_nterror(req, map_nt_error_from_unix(errno));
5217                 END_PROFILE(SMBsplwr);
5218                 return;
5219         }
5220
5221         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5222
5223         END_PROFILE(SMBsplwr);
5224         return;
5225 }
5226
5227 /****************************************************************************
5228  Reply to a mkdir.
5229 ****************************************************************************/
5230
5231 void reply_mkdir(struct smb_request *req)
5232 {
5233         connection_struct *conn = req->conn;
5234         struct smb_filename *smb_dname = NULL;
5235         char *directory = NULL;
5236         NTSTATUS status;
5237         TALLOC_CTX *ctx = talloc_tos();
5238
5239         START_PROFILE(SMBmkdir);
5240
5241         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5242                             STR_TERMINATE, &status);
5243         if (!NT_STATUS_IS_OK(status)) {
5244                 reply_nterror(req, status);
5245                 goto out;
5246         }
5247
5248         status = filename_convert(ctx, conn,
5249                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5250                                  directory,
5251                                  0,
5252                                  NULL,
5253                                  &smb_dname);
5254         if (!NT_STATUS_IS_OK(status)) {
5255                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5256                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5257                                         ERRSRV, ERRbadpath);
5258                         goto out;
5259                 }
5260                 reply_nterror(req, status);
5261                 goto out;
5262         }
5263
5264         status = create_directory(conn, req, smb_dname);
5265
5266         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5267
5268         if (!NT_STATUS_IS_OK(status)) {
5269
5270                 if (!use_nt_status()
5271                     && NT_STATUS_EQUAL(status,
5272                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5273                         /*
5274                          * Yes, in the DOS error code case we get a
5275                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5276                          * samba4 torture test.
5277                          */
5278                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5279                 }
5280
5281                 reply_nterror(req, status);
5282                 goto out;
5283         }
5284
5285         reply_outbuf(req, 0, 0);
5286
5287         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5288  out:
5289         TALLOC_FREE(smb_dname);
5290         END_PROFILE(SMBmkdir);
5291         return;
5292 }
5293
5294 /****************************************************************************
5295  Static function used by reply_rmdir to delete an entire directory
5296  tree recursively. Return True on ok, False on fail.
5297 ****************************************************************************/
5298
5299 static bool recursive_rmdir(TALLOC_CTX *ctx,
5300                         connection_struct *conn,
5301                         struct smb_filename *smb_dname)
5302 {
5303         char *dname = NULL;
5304         bool ret = True;
5305         long offset = 0;
5306         SMB_STRUCT_STAT st;
5307         struct smb_Dir *dir_hnd;
5308
5309         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5310
5311         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5312         if(dir_hnd == NULL)
5313                 return False;
5314
5315         while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5316                 struct smb_filename *smb_dname_full = NULL;
5317                 char *fullname = NULL;
5318                 bool do_break = true;
5319                 NTSTATUS status;
5320
5321                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5322                         TALLOC_FREE(dname);
5323                         continue;
5324                 }
5325
5326                 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5327                                      false)) {
5328                         TALLOC_FREE(dname);
5329                         continue;
5330                 }
5331
5332                 /* Construct the full name. */
5333                 fullname = talloc_asprintf(ctx,
5334                                 "%s/%s",
5335                                 smb_dname->base_name,
5336                                 dname);
5337                 if (!fullname) {
5338                         errno = ENOMEM;
5339                         goto err_break;
5340                 }
5341
5342                 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5343                                                     NULL, NULL,
5344                                                     &smb_dname_full);
5345                 if (!NT_STATUS_IS_OK(status)) {
5346                         goto err_break;
5347                 }
5348
5349                 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5350                         goto err_break;
5351                 }
5352
5353                 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5354                         if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5355                                 goto err_break;
5356                         }
5357                         if(SMB_VFS_RMDIR(conn,
5358                                          smb_dname_full->base_name) != 0) {
5359                                 goto err_break;
5360                         }
5361                 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5362                         goto err_break;
5363                 }
5364
5365                 /* Successful iteration. */
5366                 do_break = false;
5367
5368          err_break:
5369                 TALLOC_FREE(smb_dname_full);
5370                 TALLOC_FREE(fullname);
5371                 TALLOC_FREE(dname);
5372                 if (do_break) {
5373                         ret = false;
5374                         break;
5375                 }
5376         }
5377         TALLOC_FREE(dir_hnd);
5378         return ret;
5379 }
5380
5381 /****************************************************************************
5382  The internals of the rmdir code - called elsewhere.
5383 ****************************************************************************/
5384
5385 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5386                          connection_struct *conn,
5387                          struct smb_filename *smb_dname)
5388 {
5389         int ret;
5390         SMB_STRUCT_STAT st;
5391
5392         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5393
5394         /* Might be a symlink. */
5395         if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5396                 return map_nt_error_from_unix(errno);
5397         }
5398
5399         if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5400                 /* Is what it points to a directory ? */
5401                 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5402                         return map_nt_error_from_unix(errno);
5403                 }
5404                 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5405                         return NT_STATUS_NOT_A_DIRECTORY;
5406                 }
5407                 ret = SMB_VFS_UNLINK(conn, smb_dname);
5408         } else {
5409                 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5410         }
5411         if (ret == 0) {
5412                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5413                              FILE_NOTIFY_CHANGE_DIR_NAME,
5414                              smb_dname->base_name);
5415                 return NT_STATUS_OK;
5416         }
5417
5418         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5419                 /*
5420                  * Check to see if the only thing in this directory are
5421                  * vetoed files/directories. If so then delete them and
5422                  * retry. If we fail to delete any of them (and we *don't*
5423                  * do a recursive delete) then fail the rmdir.
5424                  */
5425                 char *dname = NULL;
5426                 long dirpos = 0;
5427                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5428                                                   smb_dname->base_name, NULL,
5429                                                   0);
5430
5431                 if(dir_hnd == NULL) {
5432                         errno = ENOTEMPTY;
5433                         goto err;
5434                 }
5435
5436                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5437                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
5438                                 TALLOC_FREE(dname);
5439                                 continue;
5440                         }
5441                         if (!is_visible_file(conn, smb_dname->base_name, dname,
5442                                              &st, false)) {
5443                                 TALLOC_FREE(dname);
5444                                 continue;
5445                         }
5446                         if(!IS_VETO_PATH(conn, dname)) {
5447                                 TALLOC_FREE(dir_hnd);
5448                                 TALLOC_FREE(dname);
5449                                 errno = ENOTEMPTY;
5450                                 goto err;
5451                         }
5452                         TALLOC_FREE(dname);
5453                 }
5454
5455                 /* We only have veto files/directories.
5456                  * Are we allowed to delete them ? */
5457
5458                 if(!lp_recursive_veto_delete(SNUM(conn))) {
5459                         TALLOC_FREE(dir_hnd);
5460                         errno = ENOTEMPTY;
5461                         goto err;
5462                 }
5463
5464                 /* Do a recursive delete. */
5465                 RewindDir(dir_hnd,&dirpos);
5466                 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5467                         struct smb_filename *smb_dname_full = NULL;
5468                         char *fullname = NULL;
5469                         bool do_break = true;
5470                         NTSTATUS status;
5471
5472                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5473                                 TALLOC_FREE(dname);
5474                                 continue;
5475                         }
5476                         if (!is_visible_file(conn, smb_dname->base_name, dname,
5477                                              &st, false)) {
5478                                 TALLOC_FREE(dname);
5479                                 continue;
5480                         }
5481
5482                         fullname = talloc_asprintf(ctx,
5483                                         "%s/%s",
5484                                         smb_dname->base_name,
5485                                         dname);
5486
5487                         if(!fullname) {
5488                                 errno = ENOMEM;
5489                                 goto err_break;
5490                         }
5491
5492                         status = create_synthetic_smb_fname(talloc_tos(),
5493                                                             fullname, NULL,
5494                                                             NULL,
5495                                                             &smb_dname_full);
5496                         if (!NT_STATUS_IS_OK(status)) {
5497                                 errno = map_errno_from_nt_status(status);
5498                                 goto err_break;
5499                         }
5500
5501                         if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5502                                 goto err_break;
5503                         }
5504                         if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5505                                 if(!recursive_rmdir(ctx, conn,
5506                                                     smb_dname_full)) {
5507                                         goto err_break;
5508                                 }
5509                                 if(SMB_VFS_RMDIR(conn,
5510                                         smb_dname_full->base_name) != 0) {
5511                                         goto err_break;
5512                                 }
5513                         } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5514                                 goto err_break;
5515                         }
5516
5517                         /* Successful iteration. */
5518                         do_break = false;
5519
5520                  err_break:
5521                         TALLOC_FREE(fullname);
5522                         TALLOC_FREE(smb_dname_full);
5523                         TALLOC_FREE(dname);
5524                         if (do_break)
5525                                 break;
5526                 }
5527                 TALLOC_FREE(dir_hnd);
5528                 /* Retry the rmdir */
5529                 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5530         }
5531
5532   err:
5533
5534         if (ret != 0) {
5535                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5536                          "%s\n", smb_fname_str_dbg(smb_dname),
5537                          strerror(errno)));
5538                 return map_nt_error_from_unix(errno);
5539         }
5540
5541         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5542                      FILE_NOTIFY_CHANGE_DIR_NAME,
5543                      smb_dname->base_name);
5544
5545         return NT_STATUS_OK;
5546 }
5547
5548 /****************************************************************************
5549  Reply to a rmdir.
5550 ****************************************************************************/
5551
5552 void reply_rmdir(struct smb_request *req)
5553 {
5554         connection_struct *conn = req->conn;
5555         struct smb_filename *smb_dname = NULL;
5556         char *directory = NULL;
5557         NTSTATUS status;
5558         TALLOC_CTX *ctx = talloc_tos();
5559         struct smbd_server_connection *sconn = smbd_server_conn;
5560
5561         START_PROFILE(SMBrmdir);
5562
5563         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5564                             STR_TERMINATE, &status);
5565         if (!NT_STATUS_IS_OK(status)) {
5566                 reply_nterror(req, status);
5567                 goto out;
5568         }
5569
5570         status = filename_convert(ctx, conn,
5571                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5572                                  directory,
5573                                  0,
5574                                  NULL,
5575                                  &smb_dname);
5576         if (!NT_STATUS_IS_OK(status)) {
5577                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5578                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5579                                         ERRSRV, ERRbadpath);
5580                         goto out;
5581                 }
5582                 reply_nterror(req, status);
5583                 goto out;
5584         }
5585
5586         if (is_ntfs_stream_smb_fname(smb_dname)) {
5587                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5588                 goto out;
5589         }
5590
5591         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5592         status = rmdir_internals(ctx, conn, smb_dname);
5593         if (!NT_STATUS_IS_OK(status)) {
5594                 reply_nterror(req, status);
5595                 goto out;
5596         }
5597
5598         reply_outbuf(req, 0, 0);
5599
5600         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5601  out:
5602         TALLOC_FREE(smb_dname);
5603         END_PROFILE(SMBrmdir);
5604         return;
5605 }
5606
5607 /*******************************************************************
5608  Resolve wildcards in a filename rename.
5609 ********************************************************************/
5610
5611 static bool resolve_wildcards(TALLOC_CTX *ctx,
5612                                 const char *name1,
5613                                 const char *name2,
5614                                 char **pp_newname)
5615 {
5616         char *name2_copy = NULL;
5617         char *root1 = NULL;
5618         char *root2 = NULL;
5619         char *ext1 = NULL;
5620         char *ext2 = NULL;
5621         char *p,*p2, *pname1, *pname2;
5622
5623         name2_copy = talloc_strdup(ctx, name2);
5624         if (!name2_copy) {
5625                 return False;
5626         }
5627
5628         pname1 = strrchr_m(name1,'/');
5629         pname2 = strrchr_m(name2_copy,'/');
5630
5631         if (!pname1 || !pname2) {
5632                 return False;
5633         }
5634
5635         /* Truncate the copy of name2 at the last '/' */
5636         *pname2 = '\0';
5637
5638         /* Now go past the '/' */
5639         pname1++;
5640         pname2++;
5641
5642         root1 = talloc_strdup(ctx, pname1);
5643         root2 = talloc_strdup(ctx, pname2);
5644
5645         if (!root1 || !root2) {
5646                 return False;
5647         }
5648
5649         p = strrchr_m(root1,'.');
5650         if (p) {
5651                 *p = 0;
5652                 ext1 = talloc_strdup(ctx, p+1);
5653         } else {
5654                 ext1 = talloc_strdup(ctx, "");
5655         }
5656         p = strrchr_m(root2,'.');
5657         if (p) {
5658                 *p = 0;
5659                 ext2 = talloc_strdup(ctx, p+1);
5660         } else {
5661                 ext2 = talloc_strdup(ctx, "");
5662         }
5663
5664         if (!ext1 || !ext2) {
5665                 return False;
5666         }
5667
5668         p = root1;
5669         p2 = root2;
5670         while (*p2) {
5671                 if (*p2 == '?') {
5672                         /* Hmmm. Should this be mb-aware ? */
5673                         *p2 = *p;
5674                         p2++;
5675                 } else if (*p2 == '*') {
5676                         *p2 = '\0';
5677                         root2 = talloc_asprintf(ctx, "%s%s",
5678                                                 root2,
5679                                                 p);
5680                         if (!root2) {
5681                                 return False;
5682                         }
5683                         break;
5684                 } else {
5685                         p2++;
5686                 }
5687                 if (*p) {
5688                         p++;
5689                 }
5690         }
5691
5692         p = ext1;
5693         p2 = ext2;
5694         while (*p2) {
5695                 if (*p2 == '?') {
5696                         /* Hmmm. Should this be mb-aware ? */
5697                         *p2 = *p;
5698                         p2++;
5699                 } else if (*p2 == '*') {
5700                         *p2 = '\0';
5701                         ext2 = talloc_asprintf(ctx, "%s%s",
5702                                                 ext2,
5703                                                 p);
5704                         if (!ext2) {
5705                                 return False;
5706                         }
5707                         break;
5708                 } else {
5709                         p2++;
5710                 }
5711                 if (*p) {
5712                         p++;
5713                 }
5714         }
5715
5716         if (*ext2) {
5717                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5718                                 name2_copy,
5719                                 root2,
5720                                 ext2);
5721         } else {
5722                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5723                                 name2_copy,
5724                                 root2);
5725         }
5726
5727         if (!*pp_newname) {
5728                 return False;
5729         }
5730
5731         return True;
5732 }
5733
5734 /****************************************************************************
5735  Ensure open files have their names updated. Updated to notify other smbd's
5736  asynchronously.
5737 ****************************************************************************/
5738
5739 static void rename_open_files(connection_struct *conn,
5740                               struct share_mode_lock *lck,
5741                               const struct smb_filename *smb_fname_dst)
5742 {
5743         files_struct *fsp;
5744         bool did_rename = False;
5745         NTSTATUS status;
5746
5747         for(fsp = file_find_di_first(lck->id); fsp;
5748             fsp = file_find_di_next(fsp)) {
5749                 /* fsp_name is a relative path under the fsp. To change this for other
5750                    sharepaths we need to manipulate relative paths. */
5751                 /* TODO - create the absolute path and manipulate the newname
5752                    relative to the sharepath. */
5753                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5754                         continue;
5755                 }
5756                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5757                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5758                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5759                            smb_fname_str_dbg(smb_fname_dst)));
5760
5761                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5762                 if (NT_STATUS_IS_OK(status)) {
5763                         did_rename = True;
5764                 }
5765         }
5766
5767         if (!did_rename) {
5768                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5769                            "for %s\n", file_id_string_tos(&lck->id),
5770                            smb_fname_str_dbg(smb_fname_dst)));
5771         }
5772
5773         /* Send messages to all smbd's (not ourself) that the name has changed. */
5774         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5775                               smb_fname_dst);
5776
5777 }
5778
5779 /****************************************************************************
5780  We need to check if the source path is a parent directory of the destination
5781  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5782  refuse the rename with a sharing violation. Under UNIX the above call can
5783  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5784  probably need to check that the client is a Windows one before disallowing
5785  this as a UNIX client (one with UNIX extensions) can know the source is a
5786  symlink and make this decision intelligently. Found by an excellent bug
5787  report from <AndyLiebman@aol.com>.
5788 ****************************************************************************/
5789
5790 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5791                                      const struct smb_filename *smb_fname_dst)
5792 {
5793         const char *psrc = smb_fname_src->base_name;
5794         const char *pdst = smb_fname_dst->base_name;
5795         size_t slen;
5796
5797         if (psrc[0] == '.' && psrc[1] == '/') {
5798                 psrc += 2;
5799         }
5800         if (pdst[0] == '.' && pdst[1] == '/') {
5801                 pdst += 2;
5802         }
5803         if ((slen = strlen(psrc)) > strlen(pdst)) {
5804                 return False;
5805         }
5806         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5807 }
5808
5809 /*
5810  * Do the notify calls from a rename
5811  */
5812
5813 static void notify_rename(connection_struct *conn, bool is_dir,
5814                           const struct smb_filename *smb_fname_src,
5815                           const struct smb_filename *smb_fname_dst)
5816 {
5817         char *parent_dir_src = NULL;
5818         char *parent_dir_dst = NULL;
5819         uint32 mask;
5820
5821         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5822                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5823
5824         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5825                             &parent_dir_src, NULL) ||
5826             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5827                             &parent_dir_dst, NULL)) {
5828                 goto out;
5829         }
5830
5831         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5832                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5833                              smb_fname_src->base_name);
5834                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5835                              smb_fname_dst->base_name);
5836         }
5837         else {
5838                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5839                              smb_fname_src->base_name);
5840                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5841                              smb_fname_dst->base_name);
5842         }
5843
5844         /* this is a strange one. w2k3 gives an additional event for
5845            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5846            files, but not directories */
5847         if (!is_dir) {
5848                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5849                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5850                              |FILE_NOTIFY_CHANGE_CREATION,
5851                              smb_fname_dst->base_name);
5852         }
5853  out:
5854         TALLOC_FREE(parent_dir_src);
5855         TALLOC_FREE(parent_dir_dst);
5856 }
5857
5858 /****************************************************************************
5859  Rename an open file - given an fsp.
5860 ****************************************************************************/
5861
5862 NTSTATUS rename_internals_fsp(connection_struct *conn,
5863                         files_struct *fsp,
5864                         const struct smb_filename *smb_fname_dst_in,
5865                         uint32 attrs,
5866                         bool replace_if_exists)
5867 {
5868         TALLOC_CTX *ctx = talloc_tos();
5869         struct smb_filename *smb_fname_dst = NULL;
5870         NTSTATUS status = NT_STATUS_OK;
5871         struct share_mode_lock *lck = NULL;
5872         bool dst_exists, old_is_stream, new_is_stream;
5873
5874         status = check_name(conn, smb_fname_dst_in->base_name);
5875         if (!NT_STATUS_IS_OK(status)) {
5876                 return status;
5877         }
5878
5879         /* Make a copy of the dst smb_fname structs */
5880
5881         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5882         if (!NT_STATUS_IS_OK(status)) {
5883                 goto out;
5884         }
5885
5886         /* Ensure the dst smb_fname contains a '/' */
5887         if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5888                 char * tmp;
5889                 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5890                                       smb_fname_dst->base_name);
5891                 if (!tmp) {
5892                         status = NT_STATUS_NO_MEMORY;
5893                         goto out;
5894                 }
5895                 TALLOC_FREE(smb_fname_dst->base_name);
5896                 smb_fname_dst->base_name = tmp;
5897         }
5898
5899         /*
5900          * Check for special case with case preserving and not
5901          * case sensitive. If the old last component differs from the original
5902          * last component only by case, then we should allow
5903          * the rename (user is trying to change the case of the
5904          * filename).
5905          */
5906         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5907             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5908             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5909                 char *last_slash;
5910                 char *fname_dst_lcomp_base_mod = NULL;
5911                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5912
5913                 /*
5914                  * Get the last component of the destination name.  Note that
5915                  * we guarantee that destination name contains a '/' character
5916                  * above.
5917                  */
5918                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5919                 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5920                 if (!fname_dst_lcomp_base_mod) {
5921                         status = NT_STATUS_NO_MEMORY;
5922                         goto out;
5923                 }
5924
5925                 /*
5926                  * Create an smb_filename struct using the original last
5927                  * component of the destination.
5928                  */
5929                 status = create_synthetic_smb_fname_split(ctx,
5930                     smb_fname_dst->original_lcomp, NULL,
5931                     &smb_fname_orig_lcomp);
5932                 if (!NT_STATUS_IS_OK(status)) {
5933                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5934                         goto out;
5935                 }
5936
5937                 /* If the base names only differ by case, use original. */
5938                 if(!strcsequal(fname_dst_lcomp_base_mod,
5939                                smb_fname_orig_lcomp->base_name)) {
5940                         char *tmp;
5941                         /*
5942                          * Replace the modified last component with the
5943                          * original.
5944                          */
5945                         *last_slash = '\0'; /* Truncate at the '/' */
5946                         tmp = talloc_asprintf(smb_fname_dst,
5947                                         "%s/%s",
5948                                         smb_fname_dst->base_name,
5949                                         smb_fname_orig_lcomp->base_name);
5950                         if (tmp == NULL) {
5951                                 status = NT_STATUS_NO_MEMORY;
5952                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5953                                 TALLOC_FREE(smb_fname_orig_lcomp);
5954                                 goto out;
5955                         }
5956                         TALLOC_FREE(smb_fname_dst->base_name);
5957                         smb_fname_dst->base_name = tmp;
5958                 }
5959
5960                 /* If the stream_names only differ by case, use original. */
5961                 if(!strcsequal(smb_fname_dst->stream_name,
5962                                smb_fname_orig_lcomp->stream_name)) {
5963                         char *tmp = NULL;
5964                         /* Use the original stream. */
5965                         tmp = talloc_strdup(smb_fname_dst,
5966                                             smb_fname_orig_lcomp->stream_name);
5967                         if (tmp == NULL) {
5968                                 status = NT_STATUS_NO_MEMORY;
5969                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5970                                 TALLOC_FREE(smb_fname_orig_lcomp);
5971                                 goto out;
5972                         }
5973                         TALLOC_FREE(smb_fname_dst->stream_name);
5974                         smb_fname_dst->stream_name = tmp;
5975                 }
5976                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5977                 TALLOC_FREE(smb_fname_orig_lcomp);
5978         }
5979
5980         /*
5981          * If the src and dest names are identical - including case,
5982          * don't do the rename, just return success.
5983          */
5984
5985         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5986             strcsequal(fsp->fsp_name->stream_name,
5987                        smb_fname_dst->stream_name)) {
5988                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5989                           "- returning success\n",
5990                           smb_fname_str_dbg(smb_fname_dst)));
5991                 status = NT_STATUS_OK;
5992                 goto out;
5993         }
5994
5995         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5996         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5997
5998         /* Return the correct error code if both names aren't streams. */
5999         if (!old_is_stream && new_is_stream) {
6000                 status = NT_STATUS_OBJECT_NAME_INVALID;
6001                 goto out;
6002         }
6003
6004         if (old_is_stream && !new_is_stream) {
6005                 status = NT_STATUS_INVALID_PARAMETER;
6006                 goto out;
6007         }
6008
6009         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6010
6011         if(!replace_if_exists && dst_exists) {
6012                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6013                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6014                           smb_fname_str_dbg(smb_fname_dst)));
6015                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6016                 goto out;
6017         }
6018
6019         if (dst_exists) {
6020                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6021                     &smb_fname_dst->st);
6022                 files_struct *dst_fsp = file_find_di_first(fileid);
6023                 /* The file can be open when renaming a stream */
6024                 if (dst_fsp && !new_is_stream) {
6025                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6026                         status = NT_STATUS_ACCESS_DENIED;
6027                         goto out;
6028                 }
6029         }
6030
6031         /* Ensure we have a valid stat struct for the source. */
6032         status = vfs_stat_fsp(fsp);
6033         if (!NT_STATUS_IS_OK(status)) {
6034                 goto out;
6035         }
6036
6037         status = can_rename(conn, fsp, attrs, &fsp->fsp_name->st);
6038
6039         if (!NT_STATUS_IS_OK(status)) {
6040                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6041                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6042                           smb_fname_str_dbg(smb_fname_dst)));
6043                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6044                         status = NT_STATUS_ACCESS_DENIED;
6045                 goto out;
6046         }
6047
6048         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6049                 status = NT_STATUS_ACCESS_DENIED;
6050         }
6051
6052         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6053                                   NULL);
6054
6055         /*
6056          * We have the file open ourselves, so not being able to get the
6057          * corresponding share mode lock is a fatal error.
6058          */
6059
6060         SMB_ASSERT(lck != NULL);
6061
6062         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6063                 uint32 create_options = fsp->fh->private_options;
6064
6065                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6066                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6067                           smb_fname_str_dbg(smb_fname_dst)));
6068
6069                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6070                               smb_fname_dst);
6071
6072                 rename_open_files(conn, lck, smb_fname_dst);
6073
6074                 /*
6075                  * A rename acts as a new file create w.r.t. allowing an initial delete
6076                  * on close, probably because in Windows there is a new handle to the
6077                  * new file. If initial delete on close was requested but not
6078                  * originally set, we need to set it here. This is probably not 100% correct,
6079                  * but will work for the CIFSFS client which in non-posix mode
6080                  * depends on these semantics. JRA.
6081                  */
6082
6083                 if (create_options & FILE_DELETE_ON_CLOSE) {
6084                         status = can_set_delete_on_close(fsp, True, 0);
6085
6086                         if (NT_STATUS_IS_OK(status)) {
6087                                 /* Note that here we set the *inital* delete on close flag,
6088                                  * not the regular one. The magic gets handled in close. */
6089                                 fsp->initial_delete_on_close = True;
6090                         }
6091                 }
6092                 TALLOC_FREE(lck);
6093                 status = NT_STATUS_OK;
6094                 goto out;
6095         }
6096
6097         TALLOC_FREE(lck);
6098
6099         if (errno == ENOTDIR || errno == EISDIR) {
6100                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6101         } else {
6102                 status = map_nt_error_from_unix(errno);
6103         }
6104
6105         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6106                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6107                   smb_fname_str_dbg(smb_fname_dst)));
6108
6109  out:
6110         TALLOC_FREE(smb_fname_dst);
6111
6112         return status;
6113 }
6114
6115 /****************************************************************************
6116  The guts of the rename command, split out so it may be called by the NT SMB
6117  code.
6118 ****************************************************************************/
6119
6120 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6121                         connection_struct *conn,
6122                         struct smb_request *req,
6123                         struct smb_filename *smb_fname_src,
6124                         struct smb_filename *smb_fname_dst,
6125                         uint32 attrs,
6126                         bool replace_if_exists,
6127                         bool src_has_wild,
6128                         bool dest_has_wild,
6129                         uint32_t access_mask)
6130 {
6131         char *fname_src_dir = NULL;
6132         char *fname_src_mask = NULL;
6133         int count=0;
6134         NTSTATUS status = NT_STATUS_OK;
6135         struct smb_Dir *dir_hnd = NULL;
6136         char *dname = NULL;
6137         long offset = 0;
6138         int create_options = 0;
6139         bool posix_pathnames = lp_posix_pathnames();
6140
6141         /*
6142          * Split the old name into directory and last component
6143          * strings. Note that unix_convert may have stripped off a
6144          * leading ./ from both name and newname if the rename is
6145          * at the root of the share. We need to make sure either both
6146          * name and newname contain a / character or neither of them do
6147          * as this is checked in resolve_wildcards().
6148          */
6149
6150         /* Split up the directory from the filename/mask. */
6151         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6152                                       &fname_src_dir, &fname_src_mask);
6153         if (!NT_STATUS_IS_OK(status)) {
6154                 status = NT_STATUS_NO_MEMORY;
6155                 goto out;
6156         }
6157
6158         /*
6159          * We should only check the mangled cache
6160          * here if unix_convert failed. This means
6161          * that the path in 'mask' doesn't exist
6162          * on the file system and so we need to look
6163          * for a possible mangle. This patch from
6164          * Tine Smukavec <valentin.smukavec@hermes.si>.
6165          */
6166
6167         if (!VALID_STAT(smb_fname_src->st) &&
6168             mangle_is_mangled(fname_src_mask, conn->params)) {
6169                 char *new_mask = NULL;
6170                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6171                                             conn->params);
6172                 if (new_mask) {
6173                         TALLOC_FREE(fname_src_mask);
6174                         fname_src_mask = new_mask;
6175                 }
6176         }
6177
6178         if (!src_has_wild) {
6179                 files_struct *fsp;
6180
6181                 /*
6182                  * Only one file needs to be renamed. Append the mask back
6183                  * onto the directory.
6184                  */
6185                 TALLOC_FREE(smb_fname_src->base_name);
6186                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6187                                                            "%s/%s",
6188                                                            fname_src_dir,
6189                                                            fname_src_mask);
6190                 if (!smb_fname_src->base_name) {
6191                         status = NT_STATUS_NO_MEMORY;
6192                         goto out;
6193                 }
6194
6195                 /* Ensure dst fname contains a '/' also */
6196                 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6197                         char *tmp;
6198                         tmp = talloc_asprintf(smb_fname_dst, "./%s",
6199                                               smb_fname_dst->base_name);
6200                         if (!tmp) {
6201                                 status = NT_STATUS_NO_MEMORY;
6202                                 goto out;
6203                         }
6204                         TALLOC_FREE(smb_fname_dst->base_name);
6205                         smb_fname_dst->base_name = tmp;
6206                 }
6207
6208                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6209                           "case_preserve = %d, short case preserve = %d, "
6210                           "directory = %s, newname = %s, "
6211                           "last_component_dest = %s\n",
6212                           conn->case_sensitive, conn->case_preserve,
6213                           conn->short_case_preserve,
6214                           smb_fname_str_dbg(smb_fname_src),
6215                           smb_fname_str_dbg(smb_fname_dst),
6216                           smb_fname_dst->original_lcomp));
6217
6218                 /* The dest name still may have wildcards. */
6219                 if (dest_has_wild) {
6220                         char *fname_dst_mod = NULL;
6221                         if (!resolve_wildcards(smb_fname_dst,
6222                                                smb_fname_src->base_name,
6223                                                smb_fname_dst->base_name,
6224                                                &fname_dst_mod)) {
6225                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6226                                           "%s %s failed\n",
6227                                           smb_fname_src->base_name,
6228                                           smb_fname_dst->base_name));
6229                                 status = NT_STATUS_NO_MEMORY;
6230                                 goto out;
6231                         }
6232                         TALLOC_FREE(smb_fname_dst->base_name);
6233                         smb_fname_dst->base_name = fname_dst_mod;
6234                 }
6235
6236                 ZERO_STRUCT(smb_fname_src->st);
6237                 if (posix_pathnames) {
6238                         SMB_VFS_LSTAT(conn, smb_fname_src);
6239                 } else {
6240                         SMB_VFS_STAT(conn, smb_fname_src);
6241                 }
6242
6243                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6244                         create_options |= FILE_DIRECTORY_FILE;
6245                 }
6246
6247                 status = SMB_VFS_CREATE_FILE(
6248                         conn,                           /* conn */
6249                         req,                            /* req */
6250                         0,                              /* root_dir_fid */
6251                         smb_fname_src,                  /* fname */
6252                         access_mask,                    /* access_mask */
6253                         (FILE_SHARE_READ |              /* share_access */
6254                             FILE_SHARE_WRITE),
6255                         FILE_OPEN,                      /* create_disposition*/
6256                         create_options,                 /* create_options */
6257                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6258                         0,                              /* oplock_request */
6259                         0,                              /* allocation_size */
6260                         NULL,                           /* sd */
6261                         NULL,                           /* ea_list */
6262                         &fsp,                           /* result */
6263                         NULL);                          /* pinfo */
6264
6265                 if (!NT_STATUS_IS_OK(status)) {
6266                         DEBUG(3, ("Could not open rename source %s: %s\n",
6267                                   smb_fname_str_dbg(smb_fname_src),
6268                                   nt_errstr(status)));
6269                         goto out;
6270                 }
6271
6272                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6273                                               attrs, replace_if_exists);
6274
6275                 close_file(req, fsp, NORMAL_CLOSE);
6276
6277                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6278                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6279                           smb_fname_str_dbg(smb_fname_dst)));
6280
6281                 goto out;
6282         }
6283
6284         /*
6285          * Wildcards - process each file that matches.
6286          */
6287         if (strequal(fname_src_mask, "????????.???")) {
6288                 TALLOC_FREE(fname_src_mask);
6289                 fname_src_mask = talloc_strdup(ctx, "*");
6290                 if (!fname_src_mask) {
6291                         status = NT_STATUS_NO_MEMORY;
6292                         goto out;
6293                 }
6294         }
6295
6296         status = check_name(conn, fname_src_dir);
6297         if (!NT_STATUS_IS_OK(status)) {
6298                 goto out;
6299         }
6300
6301         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6302                           attrs);
6303         if (dir_hnd == NULL) {
6304                 status = map_nt_error_from_unix(errno);
6305                 goto out;
6306         }
6307
6308         status = NT_STATUS_NO_SUCH_FILE;
6309         /*
6310          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6311          * - gentest fix. JRA
6312          */
6313
6314         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6315                 files_struct *fsp = NULL;
6316                 char *destname = NULL;
6317                 bool sysdir_entry = False;
6318
6319                 /* Quick check for "." and ".." */
6320                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6321                         if (attrs & aDIR) {
6322                                 sysdir_entry = True;
6323                         } else {
6324                                 TALLOC_FREE(dname);
6325                                 continue;
6326                         }
6327                 }
6328
6329                 if (!is_visible_file(conn, fname_src_dir, dname,
6330                                      &smb_fname_src->st, false)) {
6331                         TALLOC_FREE(dname);
6332                         continue;
6333                 }
6334
6335                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6336                         TALLOC_FREE(dname);
6337                         continue;
6338                 }
6339
6340                 if (sysdir_entry) {
6341                         status = NT_STATUS_OBJECT_NAME_INVALID;
6342                         break;
6343                 }
6344
6345                 TALLOC_FREE(smb_fname_src->base_name);
6346                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6347                                                            "%s/%s",
6348                                                            fname_src_dir,
6349                                                            dname);
6350                 if (!smb_fname_src->base_name) {
6351                         status = NT_STATUS_NO_MEMORY;
6352                         goto out;
6353                 }
6354
6355                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6356                                        smb_fname_dst->base_name,
6357                                        &destname)) {
6358                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6359                                   smb_fname_src->base_name, destname));
6360                         TALLOC_FREE(dname);
6361                         continue;
6362                 }
6363                 if (!destname) {
6364                         status = NT_STATUS_NO_MEMORY;
6365                         goto out;
6366                 }
6367
6368                 TALLOC_FREE(smb_fname_dst->base_name);
6369                 smb_fname_dst->base_name = destname;
6370
6371                 ZERO_STRUCT(smb_fname_src->st);
6372                 if (posix_pathnames) {
6373                         SMB_VFS_LSTAT(conn, smb_fname_src);
6374                 } else {
6375                         SMB_VFS_STAT(conn, smb_fname_src);
6376                 }
6377
6378                 create_options = 0;
6379
6380                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6381                         create_options |= FILE_DIRECTORY_FILE;
6382                 }
6383
6384                 status = SMB_VFS_CREATE_FILE(
6385                         conn,                           /* conn */
6386                         req,                            /* req */
6387                         0,                              /* root_dir_fid */
6388                         smb_fname_src,                  /* fname */
6389                         access_mask,                    /* access_mask */
6390                         (FILE_SHARE_READ |              /* share_access */
6391                             FILE_SHARE_WRITE),
6392                         FILE_OPEN,                      /* create_disposition*/
6393                         create_options,                 /* create_options */
6394                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6395                         0,                              /* oplock_request */
6396                         0,                              /* allocation_size */
6397                         NULL,                           /* sd */
6398                         NULL,                           /* ea_list */
6399                         &fsp,                           /* result */
6400                         NULL);                          /* pinfo */
6401
6402                 if (!NT_STATUS_IS_OK(status)) {
6403                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6404                                  "returned %s rename %s -> %s\n",
6405                                  nt_errstr(status),
6406                                  smb_fname_str_dbg(smb_fname_src),
6407                                  smb_fname_str_dbg(smb_fname_dst)));
6408                         break;
6409                 }
6410
6411                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6412                                                               dname);
6413                 if (!smb_fname_dst->original_lcomp) {
6414                         status = NT_STATUS_NO_MEMORY;
6415                         goto out;
6416                 }
6417
6418                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6419                                               attrs, replace_if_exists);
6420
6421                 close_file(req, fsp, NORMAL_CLOSE);
6422
6423                 if (!NT_STATUS_IS_OK(status)) {
6424                         DEBUG(3, ("rename_internals_fsp returned %s for "
6425                                   "rename %s -> %s\n", nt_errstr(status),
6426                                   smb_fname_str_dbg(smb_fname_src),
6427                                   smb_fname_str_dbg(smb_fname_dst)));
6428                         break;
6429                 }
6430
6431                 count++;
6432
6433                 DEBUG(3,("rename_internals: doing rename on %s -> "
6434                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6435                          smb_fname_str_dbg(smb_fname_src)));
6436                 TALLOC_FREE(dname);
6437         }
6438         TALLOC_FREE(dir_hnd);
6439
6440         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6441                 status = map_nt_error_from_unix(errno);
6442         }
6443
6444  out:
6445         TALLOC_FREE(dname);
6446         TALLOC_FREE(fname_src_dir);
6447         TALLOC_FREE(fname_src_mask);
6448         return status;
6449 }
6450
6451 /****************************************************************************
6452  Reply to a mv.
6453 ****************************************************************************/
6454
6455 void reply_mv(struct smb_request *req)
6456 {
6457         connection_struct *conn = req->conn;
6458         char *name = NULL;
6459         char *newname = NULL;
6460         const char *p;
6461         uint32 attrs;
6462         NTSTATUS status;
6463         bool src_has_wcard = False;
6464         bool dest_has_wcard = False;
6465         TALLOC_CTX *ctx = talloc_tos();
6466         struct smb_filename *smb_fname_src = NULL;
6467         struct smb_filename *smb_fname_dst = NULL;
6468
6469         START_PROFILE(SMBmv);
6470
6471         if (req->wct < 1) {
6472                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6473                 goto out;
6474         }
6475
6476         attrs = SVAL(req->vwv+0, 0);
6477
6478         p = (const char *)req->buf + 1;
6479         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6480                                        &status, &src_has_wcard);
6481         if (!NT_STATUS_IS_OK(status)) {
6482                 reply_nterror(req, status);
6483                 goto out;
6484         }
6485         p++;
6486         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6487                                        &status, &dest_has_wcard);
6488         if (!NT_STATUS_IS_OK(status)) {
6489                 reply_nterror(req, status);
6490                 goto out;
6491         }
6492
6493         status = filename_convert(ctx,
6494                                   conn,
6495                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6496                                   name,
6497                                   UCF_COND_ALLOW_WCARD_LCOMP,
6498                                   &src_has_wcard,
6499                                   &smb_fname_src);
6500
6501         if (!NT_STATUS_IS_OK(status)) {
6502                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6503                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6504                                         ERRSRV, ERRbadpath);
6505                         goto out;
6506                 }
6507                 reply_nterror(req, status);
6508                 goto out;
6509         }
6510
6511         status = filename_convert(ctx,
6512                                   conn,
6513                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6514                                   newname,
6515                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6516                                   &dest_has_wcard,
6517                                   &smb_fname_dst);
6518
6519         if (!NT_STATUS_IS_OK(status)) {
6520                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6521                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6522                                         ERRSRV, ERRbadpath);
6523                         goto out;
6524                 }
6525                 reply_nterror(req, status);
6526                 goto out;
6527         }
6528
6529         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6530                  smb_fname_str_dbg(smb_fname_dst)));
6531
6532         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6533                                   attrs, False, src_has_wcard, dest_has_wcard,
6534                                   DELETE_ACCESS);
6535         if (!NT_STATUS_IS_OK(status)) {
6536                 if (open_was_deferred(req->mid)) {
6537                         /* We have re-scheduled this call. */
6538                         goto out;
6539                 }
6540                 reply_nterror(req, status);
6541                 goto out;
6542         }
6543
6544         reply_outbuf(req, 0, 0);
6545  out:
6546         TALLOC_FREE(smb_fname_src);
6547         TALLOC_FREE(smb_fname_dst);
6548         END_PROFILE(SMBmv);
6549         return;
6550 }
6551
6552 /*******************************************************************
6553  Copy a file as part of a reply_copy.
6554 ******************************************************************/
6555
6556 /*
6557  * TODO: check error codes on all callers
6558  */
6559
6560 NTSTATUS copy_file(TALLOC_CTX *ctx,
6561                         connection_struct *conn,
6562                         struct smb_filename *smb_fname_src,
6563                         struct smb_filename *smb_fname_dst,
6564                         int ofun,
6565                         int count,
6566                         bool target_is_directory)
6567 {
6568         struct smb_filename *smb_fname_dst_tmp = NULL;
6569         SMB_OFF_T ret=-1;
6570         files_struct *fsp1,*fsp2;
6571         uint32 dosattrs;
6572         uint32 new_create_disposition;
6573         NTSTATUS status;
6574
6575
6576         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6577         if (!NT_STATUS_IS_OK(status)) {
6578                 return status;
6579         }
6580
6581         /*
6582          * If the target is a directory, extract the last component from the
6583          * src filename and append it to the dst filename
6584          */
6585         if (target_is_directory) {
6586                 const char *p;
6587
6588                 /* dest/target can't be a stream if it's a directory. */
6589                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6590
6591                 p = strrchr_m(smb_fname_src->base_name,'/');
6592                 if (p) {
6593                         p++;
6594                 } else {
6595                         p = smb_fname_src->base_name;
6596                 }
6597                 smb_fname_dst_tmp->base_name =
6598                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6599                                            p);
6600                 if (!smb_fname_dst_tmp->base_name) {
6601                         status = NT_STATUS_NO_MEMORY;
6602                         goto out;
6603                 }
6604         }
6605
6606         status = vfs_file_exist(conn, smb_fname_src);
6607         if (!NT_STATUS_IS_OK(status)) {
6608                 goto out;
6609         }
6610
6611         if (!target_is_directory && count) {
6612                 new_create_disposition = FILE_OPEN;
6613         } else {
6614                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6615                                                  NULL, NULL,
6616                                                  &new_create_disposition,
6617                                                  NULL)) {
6618                         status = NT_STATUS_INVALID_PARAMETER;
6619                         goto out;
6620                 }
6621         }
6622
6623         /* Open the src file for reading. */
6624         status = SMB_VFS_CREATE_FILE(
6625                 conn,                                   /* conn */
6626                 NULL,                                   /* req */
6627                 0,                                      /* root_dir_fid */
6628                 smb_fname_src,                          /* fname */
6629                 FILE_GENERIC_READ,                      /* access_mask */
6630                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6631                 FILE_OPEN,                              /* create_disposition*/
6632                 0,                                      /* create_options */
6633                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6634                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6635                 0,                                      /* allocation_size */
6636                 NULL,                                   /* sd */
6637                 NULL,                                   /* ea_list */
6638                 &fsp1,                                  /* result */
6639                 NULL);                                  /* psbuf */
6640
6641         if (!NT_STATUS_IS_OK(status)) {
6642                 goto out;
6643         }
6644
6645         dosattrs = dos_mode(conn, smb_fname_src);
6646
6647         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6648                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6649         }
6650
6651         /* Open the dst file for writing. */
6652         status = SMB_VFS_CREATE_FILE(
6653                 conn,                                   /* conn */
6654                 NULL,                                   /* req */
6655                 0,                                      /* root_dir_fid */
6656                 smb_fname_dst,                          /* fname */
6657                 FILE_GENERIC_WRITE,                     /* access_mask */
6658                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6659                 new_create_disposition,                 /* create_disposition*/
6660                 0,                                      /* create_options */
6661                 dosattrs,                               /* file_attributes */
6662                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6663                 0,                                      /* allocation_size */
6664                 NULL,                                   /* sd */
6665                 NULL,                                   /* ea_list */
6666                 &fsp2,                                  /* result */
6667                 NULL);                                  /* psbuf */
6668
6669         if (!NT_STATUS_IS_OK(status)) {
6670                 close_file(NULL, fsp1, ERROR_CLOSE);
6671                 goto out;
6672         }
6673
6674         if ((ofun&3) == 1) {
6675                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6676                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6677                         /*
6678                          * Stop the copy from occurring.
6679                          */
6680                         ret = -1;
6681                         smb_fname_src->st.st_ex_size = 0;
6682                 }
6683         }
6684
6685         /* Do the actual copy. */
6686         if (smb_fname_src->st.st_ex_size) {
6687                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6688         }
6689
6690         close_file(NULL, fsp1, NORMAL_CLOSE);
6691
6692         /* Ensure the modtime is set correctly on the destination file. */
6693         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6694
6695         /*
6696          * As we are opening fsp1 read-only we only expect
6697          * an error on close on fsp2 if we are out of space.
6698          * Thus we don't look at the error return from the
6699          * close of fsp1.
6700          */
6701         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6702
6703         if (!NT_STATUS_IS_OK(status)) {
6704                 goto out;
6705         }
6706
6707         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6708                 status = NT_STATUS_DISK_FULL;
6709                 goto out;
6710         }
6711
6712         status = NT_STATUS_OK;
6713
6714  out:
6715         TALLOC_FREE(smb_fname_dst_tmp);
6716         return status;
6717 }
6718
6719 /****************************************************************************
6720  Reply to a file copy.
6721 ****************************************************************************/
6722
6723 void reply_copy(struct smb_request *req)
6724 {
6725         connection_struct *conn = req->conn;
6726         struct smb_filename *smb_fname_src = NULL;
6727         struct smb_filename *smb_fname_dst = NULL;
6728         char *fname_src = NULL;
6729         char *fname_dst = NULL;
6730         char *fname_src_mask = NULL;
6731         char *fname_src_dir = NULL;
6732         const char *p;
6733         int count=0;
6734         int error = ERRnoaccess;
6735         int tid2;
6736         int ofun;
6737         int flags;
6738         bool target_is_directory=False;
6739         bool source_has_wild = False;
6740         bool dest_has_wild = False;
6741         NTSTATUS status;
6742         TALLOC_CTX *ctx = talloc_tos();
6743
6744         START_PROFILE(SMBcopy);
6745
6746         if (req->wct < 3) {
6747                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6748                 goto out;
6749         }
6750
6751         tid2 = SVAL(req->vwv+0, 0);
6752         ofun = SVAL(req->vwv+1, 0);
6753         flags = SVAL(req->vwv+2, 0);
6754
6755         p = (const char *)req->buf;
6756         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6757                                        &status, &source_has_wild);
6758         if (!NT_STATUS_IS_OK(status)) {
6759                 reply_nterror(req, status);
6760                 goto out;
6761         }
6762         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6763                                        &status, &dest_has_wild);
6764         if (!NT_STATUS_IS_OK(status)) {
6765                 reply_nterror(req, status);
6766                 goto out;
6767         }
6768
6769         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6770
6771         if (tid2 != conn->cnum) {
6772                 /* can't currently handle inter share copies XXXX */
6773                 DEBUG(3,("Rejecting inter-share copy\n"));
6774                 reply_doserror(req, ERRSRV, ERRinvdevice);
6775                 goto out;
6776         }
6777
6778         status = filename_convert(ctx, conn,
6779                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6780                                   fname_src,
6781                                   UCF_COND_ALLOW_WCARD_LCOMP,
6782                                   &source_has_wild,
6783                                   &smb_fname_src);
6784         if (!NT_STATUS_IS_OK(status)) {
6785                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6786                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6787                                         ERRSRV, ERRbadpath);
6788                         goto out;
6789                 }
6790                 reply_nterror(req, status);
6791                 goto out;
6792         }
6793
6794         status = filename_convert(ctx, conn,
6795                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6796                                   fname_dst,
6797                                   UCF_COND_ALLOW_WCARD_LCOMP,
6798                                   &dest_has_wild,
6799                                   &smb_fname_dst);
6800         if (!NT_STATUS_IS_OK(status)) {
6801                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6802                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6803                                         ERRSRV, ERRbadpath);
6804                         goto out;
6805                 }
6806                 reply_nterror(req, status);
6807                 goto out;
6808         }
6809
6810         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6811
6812         if ((flags&1) && target_is_directory) {
6813                 reply_doserror(req, ERRDOS, ERRbadfile);
6814                 goto out;
6815         }
6816
6817         if ((flags&2) && !target_is_directory) {
6818                 reply_doserror(req, ERRDOS, ERRbadpath);
6819                 goto out;
6820         }
6821
6822         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6823                 /* wants a tree copy! XXXX */
6824                 DEBUG(3,("Rejecting tree copy\n"));
6825                 reply_doserror(req, ERRSRV, ERRerror);
6826                 goto out;
6827         }
6828
6829         /* Split up the directory from the filename/mask. */
6830         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6831                                       &fname_src_dir, &fname_src_mask);
6832         if (!NT_STATUS_IS_OK(status)) {
6833                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6834                 goto out;
6835         }
6836
6837         /*
6838          * We should only check the mangled cache
6839          * here if unix_convert failed. This means
6840          * that the path in 'mask' doesn't exist
6841          * on the file system and so we need to look
6842          * for a possible mangle. This patch from
6843          * Tine Smukavec <valentin.smukavec@hermes.si>.
6844          */
6845         if (!VALID_STAT(smb_fname_src->st) &&
6846             mangle_is_mangled(fname_src_mask, conn->params)) {
6847                 char *new_mask = NULL;
6848                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6849                                             &new_mask, conn->params);
6850
6851                 /* Use demangled name if one was successfully found. */
6852                 if (new_mask) {
6853                         TALLOC_FREE(fname_src_mask);
6854                         fname_src_mask = new_mask;
6855                 }
6856         }
6857
6858         if (!source_has_wild) {
6859
6860                 /*
6861                  * Only one file needs to be copied. Append the mask back onto
6862                  * the directory.
6863                  */
6864                 TALLOC_FREE(smb_fname_src->base_name);
6865                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6866                                                            "%s/%s",
6867                                                            fname_src_dir,
6868                                                            fname_src_mask);
6869                 if (!smb_fname_src->base_name) {
6870                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6871                         goto out;
6872                 }
6873
6874                 if (dest_has_wild) {
6875                         char *fname_dst_mod = NULL;
6876                         if (!resolve_wildcards(smb_fname_dst,
6877                                                smb_fname_src->base_name,
6878                                                smb_fname_dst->base_name,
6879                                                &fname_dst_mod)) {
6880                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6881                                 goto out;
6882                         }
6883                         TALLOC_FREE(smb_fname_dst->base_name);
6884                         smb_fname_dst->base_name = fname_dst_mod;
6885                 }
6886
6887                 status = check_name(conn, smb_fname_src->base_name);
6888                 if (!NT_STATUS_IS_OK(status)) {
6889                         reply_nterror(req, status);
6890                         goto out;
6891                 }
6892
6893                 status = check_name(conn, smb_fname_dst->base_name);
6894                 if (!NT_STATUS_IS_OK(status)) {
6895                         reply_nterror(req, status);
6896                         goto out;
6897                 }
6898
6899                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6900                                    ofun, count, target_is_directory);
6901
6902                 if(!NT_STATUS_IS_OK(status)) {
6903                         reply_nterror(req, status);
6904                         goto out;
6905                 } else {
6906                         count++;
6907                 }
6908         } else {
6909                 struct smb_Dir *dir_hnd = NULL;
6910                 char *dname = NULL;
6911                 long offset = 0;
6912
6913                 /*
6914                  * There is a wildcard that requires us to actually read the
6915                  * src dir and copy each file matching the mask to the dst.
6916                  * Right now streams won't be copied, but this could
6917                  * presumably be added with a nested loop for reach dir entry.
6918                  */
6919                 SMB_ASSERT(!smb_fname_src->stream_name);
6920                 SMB_ASSERT(!smb_fname_dst->stream_name);
6921
6922                 smb_fname_src->stream_name = NULL;
6923                 smb_fname_dst->stream_name = NULL;
6924
6925                 if (strequal(fname_src_mask,"????????.???")) {
6926                         TALLOC_FREE(fname_src_mask);
6927                         fname_src_mask = talloc_strdup(ctx, "*");
6928                         if (!fname_src_mask) {
6929                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6930                                 goto out;
6931                         }
6932                 }
6933
6934                 status = check_name(conn, fname_src_dir);
6935                 if (!NT_STATUS_IS_OK(status)) {
6936                         reply_nterror(req, status);
6937                         goto out;
6938                 }
6939
6940                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6941                 if (dir_hnd == NULL) {
6942                         status = map_nt_error_from_unix(errno);
6943                         reply_nterror(req, status);
6944                         goto out;
6945                 }
6946
6947                 error = ERRbadfile;
6948
6949                 /* Iterate over the src dir copying each entry to the dst. */
6950                 while ((dname = ReadDirName(dir_hnd, &offset,
6951                                             &smb_fname_src->st))) {
6952                         char *destname = NULL;
6953
6954                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6955                                 TALLOC_FREE(dname);
6956                                 continue;
6957                         }
6958
6959                         if (!is_visible_file(conn, fname_src_dir, dname,
6960                                              &smb_fname_src->st, false)) {
6961                                 TALLOC_FREE(dname);
6962                                 continue;
6963                         }
6964
6965                         if(!mask_match(dname, fname_src_mask,
6966                                        conn->case_sensitive)) {
6967                                 TALLOC_FREE(dname);
6968                                 continue;
6969                         }
6970
6971                         error = ERRnoaccess;
6972
6973                         /* Get the src smb_fname struct setup. */
6974                         TALLOC_FREE(smb_fname_src->base_name);
6975                         smb_fname_src->base_name =
6976                             talloc_asprintf(smb_fname_src, "%s/%s",
6977                                             fname_src_dir, dname);
6978
6979                         if (!smb_fname_src->base_name) {
6980                                 TALLOC_FREE(dir_hnd);
6981                                 TALLOC_FREE(dname);
6982                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6983                                 goto out;
6984                         }
6985
6986                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6987                                                smb_fname_dst->base_name,
6988                                                &destname)) {
6989                                 TALLOC_FREE(dname);
6990                                 continue;
6991                         }
6992                         if (!destname) {
6993                                 TALLOC_FREE(dir_hnd);
6994                                 TALLOC_FREE(dname);
6995                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6996                                 goto out;
6997                         }
6998
6999                         TALLOC_FREE(smb_fname_dst->base_name);
7000                         smb_fname_dst->base_name = destname;
7001
7002                         status = check_name(conn, smb_fname_src->base_name);
7003                         if (!NT_STATUS_IS_OK(status)) {
7004                                 TALLOC_FREE(dir_hnd);
7005                                 TALLOC_FREE(dname);
7006                                 reply_nterror(req, status);
7007                                 goto out;
7008                         }
7009
7010                         status = check_name(conn, smb_fname_dst->base_name);
7011                         if (!NT_STATUS_IS_OK(status)) {
7012                                 TALLOC_FREE(dir_hnd);
7013                                 TALLOC_FREE(dname);
7014                                 reply_nterror(req, status);
7015                                 goto out;
7016                         }
7017
7018                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7019                                 smb_fname_src->base_name,
7020                                 smb_fname_dst->base_name));
7021
7022                         status = copy_file(ctx, conn, smb_fname_src,
7023                                            smb_fname_dst, ofun, count,
7024                                            target_is_directory);
7025                         if (NT_STATUS_IS_OK(status)) {
7026                                 count++;
7027                         }
7028
7029                         TALLOC_FREE(dname);
7030                 }
7031                 TALLOC_FREE(dir_hnd);
7032         }
7033
7034         if (count == 0) {
7035                 reply_doserror(req, ERRDOS, error);
7036                 goto out;
7037         }
7038
7039         reply_outbuf(req, 1, 0);
7040         SSVAL(req->outbuf,smb_vwv0,count);
7041  out:
7042         TALLOC_FREE(smb_fname_src);
7043         TALLOC_FREE(smb_fname_dst);
7044         TALLOC_FREE(fname_src);
7045         TALLOC_FREE(fname_dst);
7046         TALLOC_FREE(fname_src_mask);
7047         TALLOC_FREE(fname_src_dir);
7048
7049         END_PROFILE(SMBcopy);
7050         return;
7051 }
7052
7053 #undef DBGC_CLASS
7054 #define DBGC_CLASS DBGC_LOCKING
7055
7056 /****************************************************************************
7057  Get a lock pid, dealing with large count requests.
7058 ****************************************************************************/
7059
7060 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7061                     bool large_file_format)
7062 {
7063         if(!large_file_format)
7064                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7065         else
7066                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7067 }
7068
7069 /****************************************************************************
7070  Get a lock count, dealing with large count requests.
7071 ****************************************************************************/
7072
7073 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7074                         bool large_file_format)
7075 {
7076         uint64_t count = 0;
7077
7078         if(!large_file_format) {
7079                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7080         } else {
7081
7082 #if defined(HAVE_LONGLONG)
7083                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7084                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7085 #else /* HAVE_LONGLONG */
7086
7087                 /*
7088                  * NT4.x seems to be broken in that it sends large file (64 bit)
7089                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7090                  * negotiated. For boxes without large unsigned ints truncate the
7091                  * lock count by dropping the top 32 bits.
7092                  */
7093
7094                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7095                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7096                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7097                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7098                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7099                 }
7100
7101                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7102 #endif /* HAVE_LONGLONG */
7103         }
7104
7105         return count;
7106 }
7107
7108 #if !defined(HAVE_LONGLONG)
7109 /****************************************************************************
7110  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7111 ****************************************************************************/
7112
7113 static uint32 map_lock_offset(uint32 high, uint32 low)
7114 {
7115         unsigned int i;
7116         uint32 mask = 0;
7117         uint32 highcopy = high;
7118
7119         /*
7120          * Try and find out how many significant bits there are in high.
7121          */
7122
7123         for(i = 0; highcopy; i++)
7124                 highcopy >>= 1;
7125
7126         /*
7127          * We use 31 bits not 32 here as POSIX
7128          * lock offsets may not be negative.
7129          */
7130
7131         mask = (~0) << (31 - i);
7132
7133         if(low & mask)
7134                 return 0; /* Fail. */
7135
7136         high <<= (31 - i);
7137
7138         return (high|low);
7139 }
7140 #endif /* !defined(HAVE_LONGLONG) */
7141
7142 /****************************************************************************
7143  Get a lock offset, dealing with large offset requests.
7144 ****************************************************************************/
7145
7146 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7147                          bool large_file_format, bool *err)
7148 {
7149         uint64_t offset = 0;
7150
7151         *err = False;
7152
7153         if(!large_file_format) {
7154                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7155         } else {
7156
7157 #if defined(HAVE_LONGLONG)
7158                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7159                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7160 #else /* HAVE_LONGLONG */
7161
7162                 /*
7163                  * NT4.x seems to be broken in that it sends large file (64 bit)
7164                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7165                  * negotiated. For boxes without large unsigned ints mangle the
7166                  * lock offset by mapping the top 32 bits onto the lower 32.
7167                  */
7168
7169                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7170                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7171                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7172                         uint32 new_low = 0;
7173
7174                         if((new_low = map_lock_offset(high, low)) == 0) {
7175                                 *err = True;
7176                                 return (uint64_t)-1;
7177                         }
7178
7179                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7180                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7181                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7182                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7183                 }
7184
7185                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7186 #endif /* HAVE_LONGLONG */
7187         }
7188
7189         return offset;
7190 }
7191
7192 NTSTATUS smbd_do_locking(struct smb_request *req,
7193                          files_struct *fsp,
7194                          uint8_t type,
7195                          int32_t timeout,
7196                          uint16_t num_ulocks,
7197                          struct smbd_lock_element *ulocks,
7198                          uint16_t num_locks,
7199                          struct smbd_lock_element *locks,
7200                          bool *async)
7201 {
7202         connection_struct *conn = req->conn;
7203         int i;
7204         NTSTATUS status = NT_STATUS_OK;
7205
7206         *async = false;
7207
7208         /* Data now points at the beginning of the list
7209            of smb_unlkrng structs */
7210         for(i = 0; i < (int)num_ulocks; i++) {
7211                 struct smbd_lock_element *e = &ulocks[i];
7212
7213                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7214                           "pid %u, file %s\n",
7215                           (double)e->offset,
7216                           (double)e->count,
7217                           (unsigned int)e->smbpid,
7218                           fsp_str_dbg(fsp)));
7219
7220                 if (e->brltype != UNLOCK_LOCK) {
7221                         /* this can only happen with SMB2 */
7222                         return NT_STATUS_INVALID_PARAMETER;
7223                 }
7224
7225                 status = do_unlock(smbd_messaging_context(),
7226                                 fsp,
7227                                 e->smbpid,
7228                                 e->count,
7229                                 e->offset,
7230                                 WINDOWS_LOCK);
7231
7232                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7233                     nt_errstr(status)));
7234
7235                 if (!NT_STATUS_IS_OK(status)) {
7236                         return status;
7237                 }
7238         }
7239
7240         /* Setup the timeout in seconds. */
7241
7242         if (!lp_blocking_locks(SNUM(conn))) {
7243                 timeout = 0;
7244         }
7245
7246         /* Data now points at the beginning of the list
7247            of smb_lkrng structs */
7248
7249         for(i = 0; i < (int)num_locks; i++) {
7250                 struct smbd_lock_element *e = &locks[i];
7251
7252                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7253                           "%u, file %s timeout = %d\n",
7254                           (double)e->offset,
7255                           (double)e->count,
7256                           (unsigned int)e->smbpid,
7257                           fsp_str_dbg(fsp),
7258                           (int)timeout));
7259
7260                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7261                         struct blocking_lock_record *blr = NULL;
7262
7263                         if (lp_blocking_locks(SNUM(conn))) {
7264
7265                                 /* Schedule a message to ourselves to
7266                                    remove the blocking lock record and
7267                                    return the right error. */
7268
7269                                 blr = blocking_lock_cancel(fsp,
7270                                                 e->smbpid,
7271                                                 e->offset,
7272                                                 e->count,
7273                                                 WINDOWS_LOCK,
7274                                                 type,
7275                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7276                                 if (blr == NULL) {
7277                                         return NT_STATUS_DOS(
7278                                                         ERRDOS,
7279                                                         ERRcancelviolation);
7280                                 }
7281                         }
7282                         /* Remove a matching pending lock. */
7283                         status = do_lock_cancel(fsp,
7284                                                 e->smbpid,
7285                                                 e->count,
7286                                                 e->offset,
7287                                                 WINDOWS_LOCK,
7288                                                 blr);
7289                 } else {
7290                         bool blocking_lock = timeout ? true : false;
7291                         bool defer_lock = false;
7292                         struct byte_range_lock *br_lck;
7293                         uint32_t block_smbpid;
7294
7295                         br_lck = do_lock(smbd_messaging_context(),
7296                                         fsp,
7297                                         e->smbpid,
7298                                         e->count,
7299                                         e->offset, 
7300                                         e->brltype,
7301                                         WINDOWS_LOCK,
7302                                         blocking_lock,
7303                                         &status,
7304                                         &block_smbpid,
7305                                         NULL);
7306
7307                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7308                                 /* Windows internal resolution for blocking locks seems
7309                                    to be about 200ms... Don't wait for less than that. JRA. */
7310                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7311                                         timeout = lp_lock_spin_time();
7312                                 }
7313                                 defer_lock = true;
7314                         }
7315
7316                         /* This heuristic seems to match W2K3 very well. If a
7317                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7318                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
7319                            far as I can tell. Replacement for do_lock_spin(). JRA. */
7320
7321                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7322                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7323                                 defer_lock = true;
7324                                 timeout = lp_lock_spin_time();
7325                         }
7326
7327                         if (br_lck && defer_lock) {
7328                                 /*
7329                                  * A blocking lock was requested. Package up
7330                                  * this smb into a queued request and push it
7331                                  * onto the blocking lock queue.
7332                                  */
7333                                 if(push_blocking_lock_request(br_lck,
7334                                                         req,
7335                                                         fsp,
7336                                                         timeout,
7337                                                         i,
7338                                                         e->smbpid,
7339                                                         e->brltype,
7340                                                         WINDOWS_LOCK,
7341                                                         e->offset,
7342                                                         e->count,
7343                                                         block_smbpid)) {
7344                                         TALLOC_FREE(br_lck);
7345                                         *async = true;
7346                                         return NT_STATUS_OK;
7347                                 }
7348                         }
7349
7350                         TALLOC_FREE(br_lck);
7351                 }
7352
7353                 if (!NT_STATUS_IS_OK(status)) {
7354                         break;
7355                 }
7356         }
7357
7358         /* If any of the above locks failed, then we must unlock
7359            all of the previous locks (X/Open spec). */
7360
7361         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7362
7363                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7364                         i = -1; /* we want to skip the for loop */
7365                 }
7366
7367                 /*
7368                  * Ensure we don't do a remove on the lock that just failed,
7369                  * as under POSIX rules, if we have a lock already there, we
7370                  * will delete it (and we shouldn't) .....
7371                  */
7372                 for(i--; i >= 0; i--) {
7373                         struct smbd_lock_element *e = &locks[i];
7374
7375                         do_unlock(smbd_messaging_context(),
7376                                 fsp,
7377                                 e->smbpid,
7378                                 e->count,
7379                                 e->offset,
7380                                 WINDOWS_LOCK);
7381                 }
7382                 return status;
7383         }
7384
7385         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7386                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7387
7388         return NT_STATUS_OK;
7389 }
7390
7391 /****************************************************************************
7392  Reply to a lockingX request.
7393 ****************************************************************************/
7394
7395 void reply_lockingX(struct smb_request *req)
7396 {
7397         connection_struct *conn = req->conn;
7398         files_struct *fsp;
7399         unsigned char locktype;
7400         unsigned char oplocklevel;
7401         uint16 num_ulocks;
7402         uint16 num_locks;
7403         int32 lock_timeout;
7404         int i;
7405         const uint8_t *data;
7406         bool large_file_format;
7407         bool err;
7408         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7409         struct smbd_lock_element *ulocks;
7410         struct smbd_lock_element *locks;
7411         bool async = false;
7412
7413         START_PROFILE(SMBlockingX);
7414
7415         if (req->wct < 8) {
7416                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7417                 END_PROFILE(SMBlockingX);
7418                 return;
7419         }
7420
7421         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7422         locktype = CVAL(req->vwv+3, 0);
7423         oplocklevel = CVAL(req->vwv+3, 1);
7424         num_ulocks = SVAL(req->vwv+6, 0);
7425         num_locks = SVAL(req->vwv+7, 0);
7426         lock_timeout = IVAL(req->vwv+4, 0);
7427         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7428
7429         if (!check_fsp(conn, req, fsp)) {
7430                 END_PROFILE(SMBlockingX);
7431                 return;
7432         }
7433
7434         data = req->buf;
7435
7436         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7437                 /* we don't support these - and CANCEL_LOCK makes w2k
7438                    and XP reboot so I don't really want to be
7439                    compatible! (tridge) */
7440                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7441                 END_PROFILE(SMBlockingX);
7442                 return;
7443         }
7444
7445         /* Check if this is an oplock break on a file
7446            we have granted an oplock on.
7447         */
7448         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7449                 /* Client can insist on breaking to none. */
7450                 bool break_to_none = (oplocklevel == 0);
7451                 bool result;
7452
7453                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7454                          "for fnum = %d\n", (unsigned int)oplocklevel,
7455                          fsp->fnum ));
7456
7457                 /*
7458                  * Make sure we have granted an exclusive or batch oplock on
7459                  * this file.
7460                  */
7461
7462                 if (fsp->oplock_type == 0) {
7463
7464                         /* The Samba4 nbench simulator doesn't understand
7465                            the difference between break to level2 and break
7466                            to none from level2 - it sends oplock break
7467                            replies in both cases. Don't keep logging an error
7468                            message here - just ignore it. JRA. */
7469
7470                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7471                                  "client for fnum = %d (oplock=%d) and no "
7472                                  "oplock granted on this file (%s).\n",
7473                                  fsp->fnum, fsp->oplock_type,
7474                                  fsp_str_dbg(fsp)));
7475
7476                         /* if this is a pure oplock break request then don't
7477                          * send a reply */
7478                         if (num_locks == 0 && num_ulocks == 0) {
7479                                 END_PROFILE(SMBlockingX);
7480                                 return;
7481                         } else {
7482                                 END_PROFILE(SMBlockingX);
7483                                 reply_doserror(req, ERRDOS, ERRlock);
7484                                 return;
7485                         }
7486                 }
7487
7488                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7489                     (break_to_none)) {
7490                         result = remove_oplock(fsp);
7491                 } else {
7492                         result = downgrade_oplock(fsp);
7493                 }
7494
7495                 if (!result) {
7496                         DEBUG(0, ("reply_lockingX: error in removing "
7497                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7498                         /* Hmmm. Is this panic justified? */
7499                         smb_panic("internal tdb error");
7500                 }
7501
7502                 reply_to_oplock_break_requests(fsp);
7503
7504                 /* if this is a pure oplock break request then don't send a
7505                  * reply */
7506                 if (num_locks == 0 && num_ulocks == 0) {
7507                         /* Sanity check - ensure a pure oplock break is not a
7508                            chained request. */
7509                         if(CVAL(req->vwv+0, 0) != 0xff)
7510                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7511                                          "break is a chained %d request !\n",
7512                                          (unsigned int)CVAL(req->vwv+0, 0)));
7513                         END_PROFILE(SMBlockingX);
7514                         return;
7515                 }
7516         }
7517
7518         if (req->buflen <
7519             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7520                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7521                 END_PROFILE(SMBlockingX);
7522                 return;
7523         }
7524
7525         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7526         if (ulocks == NULL) {
7527                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7528                 END_PROFILE(SMBlockingX);
7529                 return;
7530         }
7531
7532         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7533         if (locks == NULL) {
7534                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7535                 END_PROFILE(SMBlockingX);
7536                 return;
7537         }
7538
7539         /* Data now points at the beginning of the list
7540            of smb_unlkrng structs */
7541         for(i = 0; i < (int)num_ulocks; i++) {
7542                 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7543                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7544                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7545                 ulocks[i].brltype = UNLOCK_LOCK;
7546
7547                 /*
7548                  * There is no error code marked "stupid client bug".... :-).
7549                  */
7550                 if(err) {
7551                         END_PROFILE(SMBlockingX);
7552                         reply_doserror(req, ERRDOS, ERRnoaccess);
7553                         return;
7554                 }
7555         }
7556
7557         /* Now do any requested locks */
7558         data += ((large_file_format ? 20 : 10)*num_ulocks);
7559
7560         /* Data now points at the beginning of the list
7561            of smb_lkrng structs */
7562
7563         for(i = 0; i < (int)num_locks; i++) {
7564                 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7565                 locks[i].count = get_lock_count(data, i, large_file_format);
7566                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7567
7568                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7569                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7570                                 locks[i].brltype = PENDING_READ_LOCK;
7571                         } else {
7572                                 locks[i].brltype = READ_LOCK;
7573                         }
7574                 } else {
7575                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7576                                 locks[i].brltype = PENDING_WRITE_LOCK;
7577                         } else {
7578                                 locks[i].brltype = WRITE_LOCK;
7579                         }
7580                 }
7581
7582                 /*
7583                  * There is no error code marked "stupid client bug".... :-).
7584                  */
7585                 if(err) {
7586                         END_PROFILE(SMBlockingX);
7587                         reply_doserror(req, ERRDOS, ERRnoaccess);
7588                         return;
7589                 }
7590         }
7591
7592         status = smbd_do_locking(req, fsp,
7593                                  locktype, lock_timeout,
7594                                  num_ulocks, ulocks,
7595                                  num_locks, locks,
7596                                  &async);
7597         if (!NT_STATUS_IS_OK(status)) {
7598                 END_PROFILE(SMBlockingX);
7599                 reply_nterror(req, status);
7600                 return;
7601         }
7602         if (async) {
7603                 END_PROFILE(SMBlockingX);
7604                 return;
7605         }
7606
7607         reply_outbuf(req, 2, 0);
7608
7609         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7610                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7611
7612         END_PROFILE(SMBlockingX);
7613         chain_reply(req);
7614 }
7615
7616 #undef DBGC_CLASS
7617 #define DBGC_CLASS DBGC_ALL
7618
7619 /****************************************************************************
7620  Reply to a SMBreadbmpx (read block multiplex) request.
7621  Always reply with an error, if someone has a platform really needs this,
7622  please contact vl@samba.org
7623 ****************************************************************************/
7624
7625 void reply_readbmpx(struct smb_request *req)
7626 {
7627         START_PROFILE(SMBreadBmpx);
7628         reply_doserror(req, ERRSRV, ERRuseSTD);
7629         END_PROFILE(SMBreadBmpx);
7630         return;
7631 }
7632
7633 /****************************************************************************
7634  Reply to a SMBreadbs (read block multiplex secondary) request.
7635  Always reply with an error, if someone has a platform really needs this,
7636  please contact vl@samba.org
7637 ****************************************************************************/
7638
7639 void reply_readbs(struct smb_request *req)
7640 {
7641         START_PROFILE(SMBreadBs);
7642         reply_doserror(req, ERRSRV, ERRuseSTD);
7643         END_PROFILE(SMBreadBs);
7644         return;
7645 }
7646
7647 /****************************************************************************
7648  Reply to a SMBsetattrE.
7649 ****************************************************************************/
7650
7651 void reply_setattrE(struct smb_request *req)
7652 {
7653         connection_struct *conn = req->conn;
7654         struct smb_file_time ft;
7655         files_struct *fsp;
7656         NTSTATUS status;
7657
7658         START_PROFILE(SMBsetattrE);
7659         ZERO_STRUCT(ft);
7660
7661         if (req->wct < 7) {
7662                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7663                 goto out;
7664         }
7665
7666         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7667
7668         if(!fsp || (fsp->conn != conn)) {
7669                 reply_doserror(req, ERRDOS, ERRbadfid);
7670                 goto out;
7671         }
7672
7673         /*
7674          * Convert the DOS times into unix times.
7675          */
7676
7677         ft.atime = convert_time_t_to_timespec(
7678             srv_make_unix_date2(req->vwv+3));
7679         ft.mtime = convert_time_t_to_timespec(
7680             srv_make_unix_date2(req->vwv+5));
7681         ft.create_time = convert_time_t_to_timespec(
7682             srv_make_unix_date2(req->vwv+1));
7683
7684         reply_outbuf(req, 0, 0);
7685
7686         /* 
7687          * Patch from Ray Frush <frush@engr.colostate.edu>
7688          * Sometimes times are sent as zero - ignore them.
7689          */
7690
7691         /* Ensure we have a valid stat struct for the source. */
7692         status = vfs_stat_fsp(fsp);
7693         if (!NT_STATUS_IS_OK(status)) {
7694                 reply_nterror(req, status);
7695                 goto out;
7696         }
7697
7698         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7699         if (!NT_STATUS_IS_OK(status)) {
7700                 reply_doserror(req, ERRDOS, ERRnoaccess);
7701                 goto out;
7702         }
7703
7704         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7705                " createtime=%u\n",
7706                 fsp->fnum,
7707                 (unsigned int)ft.atime.tv_sec,
7708                 (unsigned int)ft.mtime.tv_sec,
7709                 (unsigned int)ft.create_time.tv_sec
7710                 ));
7711  out:
7712         END_PROFILE(SMBsetattrE);
7713         return;
7714 }
7715
7716
7717 /* Back from the dead for OS/2..... JRA. */
7718
7719 /****************************************************************************
7720  Reply to a SMBwritebmpx (write block multiplex primary) request.
7721  Always reply with an error, if someone has a platform really needs this,
7722  please contact vl@samba.org
7723 ****************************************************************************/
7724
7725 void reply_writebmpx(struct smb_request *req)
7726 {
7727         START_PROFILE(SMBwriteBmpx);
7728         reply_doserror(req, ERRSRV, ERRuseSTD);
7729         END_PROFILE(SMBwriteBmpx);
7730         return;
7731 }
7732
7733 /****************************************************************************
7734  Reply to a SMBwritebs (write block multiplex secondary) request.
7735  Always reply with an error, if someone has a platform really needs this,
7736  please contact vl@samba.org
7737 ****************************************************************************/
7738
7739 void reply_writebs(struct smb_request *req)
7740 {
7741         START_PROFILE(SMBwriteBs);
7742         reply_doserror(req, ERRSRV, ERRuseSTD);
7743         END_PROFILE(SMBwriteBs);
7744         return;
7745 }
7746
7747 /****************************************************************************
7748  Reply to a SMBgetattrE.
7749 ****************************************************************************/
7750
7751 void reply_getattrE(struct smb_request *req)
7752 {
7753         connection_struct *conn = req->conn;
7754         int mode;
7755         files_struct *fsp;
7756         struct timespec create_ts;
7757
7758         START_PROFILE(SMBgetattrE);
7759
7760         if (req->wct < 1) {
7761                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7762                 END_PROFILE(SMBgetattrE);
7763                 return;
7764         }
7765
7766         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7767
7768         if(!fsp || (fsp->conn != conn)) {
7769                 reply_doserror(req, ERRDOS, ERRbadfid);
7770                 END_PROFILE(SMBgetattrE);
7771                 return;
7772         }
7773
7774         /* Do an fstat on this file */
7775         if(fsp_stat(fsp)) {
7776                 reply_nterror(req, map_nt_error_from_unix(errno));
7777                 END_PROFILE(SMBgetattrE);
7778                 return;
7779         }
7780
7781         mode = dos_mode(conn, fsp->fsp_name);
7782
7783         /*
7784          * Convert the times into dos times. Set create
7785          * date to be last modify date as UNIX doesn't save
7786          * this.
7787          */
7788
7789         reply_outbuf(req, 11, 0);
7790
7791         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7792         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7793         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7794                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7795         /* Should we check pending modtime here ? JRA */
7796         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7797                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7798
7799         if (mode & aDIR) {
7800                 SIVAL(req->outbuf, smb_vwv6, 0);
7801                 SIVAL(req->outbuf, smb_vwv8, 0);
7802         } else {
7803                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7804                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7805                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7806         }
7807         SSVAL(req->outbuf,smb_vwv10, mode);
7808
7809         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7810
7811         END_PROFILE(SMBgetattrE);
7812         return;
7813 }