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