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