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