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