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