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