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