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