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