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